1  /-
  2  Copyright (c) 2014 Parikshit Khanna. All rights reserved.
  3  Released under Apache 2.0 license as described in the file LICENSE.
  4  Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn, Mario Carneiro
  5  
  6  Basic properties of lists.
  7  -/
  8  import
  9    tactic.interactive tactic.mk_iff_of_inductive_prop
src    └────────────────┘ └─────────────────────────────┘
 10    logic.basic logic.function logic.relator
src    └─────────┘ └────────────┘ └───────────┘
 11    algebra.group order.basic
src    └───────────┘ └─────────┘
 12    data.list.defs data.nat.basic data.option.basic
src    └────────────┘ └────────────┘ └───────────────┘
 13    data.bool data.prod data.fin
src    └───────┘ └───────┘ └──────┘
 14  open function nat
 15  
 16  namespace list
 17  universes u v w x
 18  variables {α : Type u} {β : Type v} {γ : Type w} {δ : Type x}
 19  
 20  instance : is_left_id (list α) has_append.append [] :=
id              └────────┘  └──┘   └───────────────┘ └┘
src             └────────┘  └──┘    └───────────────┘ └┘
typ             └────────┘  └──┘   └───────────────┘ └┘
 21  ⟨ nil_append ⟩
id     └────────┘
src    └────────┘
typ    └────────┘
 22  
 23  instance : is_right_id (list α) has_append.append [] :=
id              └─────────┘  └──┘   └───────────────┘ └┘
src             └─────────┘  └──┘    └───────────────┘ └┘
typ             └─────────┘  └──┘   └───────────────┘ └┘
 24  ⟨ append_nil ⟩
id     └────────┘
src    └────────┘
typ    └────────┘
 25  
 26  instance : is_associative (list α) has_append.append :=
id              └────────────┘  └──┘   └───────────────┘
src             └────────────┘  └──┘    └───────────────┘
typ             └────────────┘  └──┘   └───────────────┘
 27  ⟨ append_assoc ⟩
id     └──────────┘
src    └──────────┘
typ    └──────────┘
 28  
 29  @[simp] theorem cons_ne_nil (a : α) (l : list α) : a::l ≠ [].
id                                           └──┘     └┘  └┘
src                                           └──┘       └┘   └┘
typ                                          └──┘     └┘  └┘
doc    └──┘
 30  
 31  theorem head_eq_of_cons_eq {h₁ h₂ : α} {t₁ t₂ : list α} :
id                                                  └──┘ 
src                                                  └──┘
typ                                                 └──┘ 
 32        (h₁::t₁) = (h₂::t₂) → h₁ = h₂ :=
id          └┘└┘└┘    └┘└┘└┘    └┘  └┘
src           └┘        └┘         
typ         └┘└┘└┘    └┘└┘└┘    └┘  └┘
 33  assume Peq, list.no_confusion Peq (assume Pheq Pteq, Pheq)
id          └─┘  └───────────────┘ └─┘         └──┘ └──┘  └──┘
src              └───────────────┘
typ         └─┘  └───────────────┘ └─┘         └──┘ └──┘  └──┘
 34  
 35  theorem tail_eq_of_cons_eq {h₁ h₂ : α} {t₁ t₂ : list α} :
id                                                  └──┘ 
src                                                  └──┘
typ                                                 └──┘ 
 36        (h₁::t₁) = (h₂::t₂) → t₁ = t₂ :=
id          └┘└┘└┘    └┘└┘└┘    └┘  └┘
src           └┘        └┘         
typ         └┘└┘└┘    └┘└┘└┘    └┘  └┘
 37  assume Peq, list.no_confusion Peq (assume Pheq Pteq, Pteq)
id          └─┘  └───────────────┘ └─┘         └──┘ └──┘  └──┘
src              └───────────────┘
typ         └─┘  └───────────────┘ └─┘         └──┘ └──┘  └──┘
 38  
 39  theorem cons_inj {a : α} : injective (cons a) :=
id                             └───────┘  └──┘ 
src                             └───────┘  └──┘
typ                            └───────┘  └──┘ 
 40  assume l₁ l₂, assume Pe, tail_eq_of_cons_eq Pe
id          └┘ └┘         └┘  └────────────────┘ └┘
src                           └────────────────┘
typ         └┘ └┘         └┘  └────────────────┘ └┘
 41  
 42  @[simp] theorem cons_inj' (a : α) {l l' : list α} : a::l = a::l' ↔ l = l' :=
id                                            └──┘     └┘  └┘└┘    └┘
src                                            └──┘       └┘    └┘      
typ                                           └──┘     └┘  └┘└┘    └┘
doc    └──┘
 43  ⟨λ e, cons_inj e, congr_arg _⟩
id        └──────┘   └───────┘
src        └──────┘    └───────┘
typ       └──────┘   └───────┘
 44  
 45  /- mem -/
 46  
 47  theorem mem_singleton_self (a : α) : a ∈ [a] := mem_cons_self _ _
id                                             └───────────┘
src                                               └───────────┘
typ                                            └───────────┘
 48  
 49  theorem eq_of_mem_singleton {a b : α} : a ∈ [b] → a = b :=
id                                                 
src                                                   
typ                                                
 50  assume : a ∈ [b], or.elim (eq_or_mem_of_mem_cons this)
id                └─────┘  └───────────────────┘ └──┘
src                 └─────┘  └───────────────────┘
typ               └─────┘  └───────────────────┘ └──┘
 51    (assume : a = b, this)
id                   └──┘
src                
typ                  └──┘
 52    (assume : a ∈ [], absurd this (not_mem_nil a))
id                 └┘  └────┘ └──┘  └─────────┘ 
src                 └┘  └────┘       └─────────┘
typ                └┘  └────┘ └──┘  └─────────┘ 
 53  
 54  @[simp] theorem mem_singleton {a b : α} : a ∈ [b] ↔ a = b :=
id                                                  
src                                                    
typ                                                 
doc    └──┘
 55  ⟨eq_of_mem_singleton, or.inl⟩
id    └─────────────────┘  └────┘
src   └─────────────────┘  └────┘
typ   └─────────────────┘  └────┘
 56  
 57  theorem mem_of_mem_cons_of_mem {a b : α} {l : list α} : a ∈ b::l → b ∈ l → a ∈ l :=
id                                                └──┘       └┘          
src                                                └──┘          └┘             
typ                                               └──┘       └┘          
 58  assume ainbl binl, or.elim (eq_or_mem_of_mem_cons ainbl)
id          └───┘ └──┘  └─────┘  └───────────────────┘ └───┘
src                     └─────┘  └───────────────────┘
typ         └───┘ └──┘  └─────┘  └───────────────────┘ └───┘
 59    (assume : a = b, begin subst a, exact binl end)
id                                       └──┘
src                          └────┘   └────┘    
typ                        └────┘  └────┘└──┘
doc                           └────┘   └────┘    
txt                           └────┘   └────┘    
par                           └────┘   └────┘    
pid                                            
st                      └───────────┘└───────────┘└─┘
 60    (assume : a ∈ l, this)
id                   └──┘
src                
typ                  └──┘
 61  
 62  theorem eq_or_ne_mem_of_mem {a b : α} {l : list α} (h : a ∈ b :: l) : a = b ∨ (a ≠ b ∧ a ∈ l) :=
id                                             └──┘           └┘                
src                                             └──┘              └┘                     
typ                                            └──┘           └┘                
 63  classical.by_cases or.inl $ assume : a ≠ b, h.elim or.inl $ assume h, or.inr ⟨this, h⟩
id   └────────────────┘ └────┘                └───┘ └────┘            └────┘  └──┘  
src  └────────────────┘ └────┘                   └───┘ └────┘             └────┘
typ  └────────────────┘ └────┘                └───┘ └────┘            └────┘  └──┘  
 64  
 65  theorem not_mem_append {a : α} {s t : list α} (h₁ : a ∉ s) (h₂ : a ∉ t) : a ∉ s ++ t :=
id                                        └──┘                            └┘ 
src                                        └──┘                                   └┘
typ                                       └──┘                            └┘ 
 66  mt mem_append.1 $ not_or_distrib.2 ⟨h₁, h₂⟩
id   └┘ └────────┘    └────────────┘   └┘  └┘
src  └┘ └────────┘    └────────────┘
typ  └┘ └────────┘    └────────────┘   └┘  └┘
 67  
 68  theorem ne_nil_of_mem {a : α} {l : list α} (h : a ∈ l) : l ≠ [] :=
id                                     └──┘                └┘
src                                     └──┘                    └┘
typ                                    └──┘                └┘
 69  by intro e; rw e at h; cases h
id                               
src     └─────┘  └─┘ └───┘  └────┘ 
typ     └─────┘  └─┘└───┘  └────┘
doc     └─────┘  └─┘ └───┘  └────┘ 
txt     └─────┘  └─┘ └───┘  └────┘ 
par     └─────┘  └─┘ └───┘  └────┘ 
pid          └┘     └───┘        
st     └───────────┘└──────────────
 70  
src  
typ  
doc  
txt  
par  
pid  
st   
 71  theorem mem_split {a : α} {l : list α} (h : a ∈ l) : ∃ s t : list α, l = s ++ a :: t :=
id                                 └──┘                     └──┘     └┘  └┘ 
src                                 └──┘                        └──┘        └┘   └┘
typ                                └──┘                     └──┘     └┘  └┘ 
 72  begin
st   └─────
 73    induction l with b l ih, {cases h}, rcases h with rfl | h,
id                                              
src    └────────┘ └──────────┘   └────┘    └─────┘ └───────────┘
typ    └────────┘└──────────┘   └────┘   └─────┘└───────────┘
doc    └────────┘ └──────────┘   └────┘    └─────┘ └───────────┘
txt    └────────┘ └──────────┘   └────┘    └─────┘ └───────────┘
par    └────────┘ └──────────┘   └────┘    └─────┘ └───────────┘
pid              └─────────┘                   └───────────┘
st   ────────────────────────┘└────────┘└┘└────────────────────┘└─
 74    { exact ⟨[], l, rfl⟩ },
id                    └─┘
src      └────┘   └┘ └┘└─┘└┘
typ      └────┘   └┘└┘└─┘└┘
doc      └────┘   └┘ └┘   └┘
txt      └────┘   └┘ └┘   └┘
par      └────┘   └┘ └┘   └┘
pid              └┘ └┘   
st   ───┘└─────────────────┘└┘
 75    { rcases ih h with ⟨s, t, rfl⟩,
id              └┘ 
src      └─────┘   └───────────────┘
typ      └─────┘└┘└───────────────┘
doc      └─────┘   └───────────────┘
txt      └─────┘   └───────────────┘
par      └─────┘   └───────────────┘
pid               └───────────────┘
st   ───────────────────────────────┘└─
 76      exact ⟨b::s, t, rfl⟩ }
id                    └─┘
src      └────┘     └┘ └┘└─┘└┘
typ      └────┘   └┘└┘└─┘└┘
doc      └────┘     └┘ └┘   └┘
txt      └────┘     └┘ └┘   └┘
par      └────┘     └┘ └┘   └┘
pid                └┘ └┘   
st   ────────────────────────┘└─
 77  end
st   ──┘
 78  
 79  theorem mem_of_ne_of_mem {a y : α} {l : list α} (h₁ : a ≠ y) (h₂ : a ∈ y :: l) : a ∈ l :=
id                                          └──┘                      └┘       
src                                          └──┘                           └┘        
typ                                         └──┘                      └┘       
 80  or.elim (eq_or_mem_of_mem_cons h₂) (λe, absurd e h₁) (λr, r)
id   └─────┘  └───────────────────┘ └┘      └────┘  └┘      
src  └─────┘  └───────────────────┘          └────┘
typ  └─────┘  └───────────────────┘ └┘      └────┘  └┘      
 81  
 82  theorem ne_of_not_mem_cons {a b : α} {l : list α} : a ∉ b::l → a ≠ b :=
id                                            └──┘       └┘     
src                                            └──┘          └┘      
typ                                           └──┘       └┘     
 83  assume nin aeqb, absurd (or.inl aeqb) nin
id          └─┘ └──┘  └────┘  └────┘ └──┘  └─┘
src                   └────┘  └────┘
typ         └─┘ └──┘  └────┘  └────┘ └──┘  └─┘
 84  
 85  theorem not_mem_of_not_mem_cons {a b : α} {l : list α} : a ∉ b::l → a ∉ l :=
id                                                 └──┘       └┘     
src                                                 └──┘          └┘      
typ                                                └──┘       └┘     
 86  assume nin nainl, absurd (or.inr nainl) nin
id          └─┘ └───┘  └────┘  └────┘ └───┘  └─┘
src                    └────┘  └────┘
typ         └─┘ └───┘  └────┘  └────┘ └───┘  └─┘
 87  
 88  theorem not_mem_cons_of_ne_of_not_mem {a y : α} {l : list α} : a ≠ y → a ∉ l → a ∉ y::l :=
id                                                       └──┘                 └┘
src                                                       └──┘                        └┘
typ                                                      └──┘                 └┘
 89  assume p1 p2, not.intro (assume Pain, absurd (eq_or_mem_of_mem_cons Pain) (not_or p1 p2))
id          └┘ └┘  └───────┘         └──┘  └────┘  └───────────────────┘ └──┘   └────┘ └┘ └┘
src                └───────┘               └────┘  └───────────────────┘        └────┘
typ         └┘ └┘  └───────┘         └──┘  └────┘  └───────────────────┘ └──┘   └────┘ └┘ └┘
 90  
 91  theorem ne_and_not_mem_of_not_mem_cons {a y : α} {l : list α} : a ∉ y::l → a ≠ y ∧ a ∉ l :=
id                                                        └──┘       └┘         
src                                                        └──┘          └┘            
typ                                                       └──┘       └┘         
 92  assume p, and.intro (ne_of_not_mem_cons p) (not_mem_of_not_mem_cons p)
id            └───────┘  └────────────────┘    └─────────────────────┘ 
src            └───────┘  └────────────────┘     └─────────────────────┘
typ           └───────┘  └────────────────┘    └─────────────────────┘ 
 93  
 94  theorem mem_map_of_mem (f : α → β) {a : α} {l : list α} (h : a ∈ l) : f a ∈ map f l :=
id                                                └──┘                 └─┘  
src                                                  └──┘                      └─┘
typ                                               └──┘                 └─┘  
 95  begin
st   └─────
 96    induction l with b l' ih,
id               
src    └────────┘ └───────────┘
typ    └────────┘└───────────┘
doc    └────────┘ └───────────┘
txt    └────────┘ └───────────┘
par    └────────┘ └───────────┘
pid              └──────────┘
st   ─────────────────────────┘└─
 97    {cases h},
id            
src     └────┘
typ     └────┘
doc     └────┘
txt     └────┘
par     └────┘
pid          
st   ─────────┘└┘
 98    {rcases h with rfl | h,
id             
src     └─────┘ └───────────┘
typ     └─────┘└───────────┘
doc     └─────┘ └───────────┘
txt     └─────┘ └───────────┘
par     └─────┘ └───────────┘
pid            └───────────┘
st   ───────────────────────┘└─
 99      {exact or.inl rfl},
id              └────┘ └─┘
src       └────┘└────┘└─┘
typ       └────┘└────┘└─┘
doc       └────┘      
txt       └────┘      
par       └────┘      
pid                  
st   ────────────────────┘└┘
100      {exact or.inr (ih h)}}
id              └────┘  └┘ 
src       └────┘└────┘    
typ       └────┘└────┘ └┘
doc       └────┘          
txt       └────┘          
par       └────┘          
pid                      
st   ───────────────────────┘└──
101  end
st   ──┘
102  
103  theorem exists_of_mem_map {f : α → β} {b : β} {l : list α} (h : b ∈ map f l) : ∃ a, a ∈ l ∧ f a = b :=
id                                                   └──┘          └─┘               
src                                                     └──┘            └─┘                     
typ                                                  └──┘          └─┘               
104  begin
st   └─────
105    induction l with c l' ih,
id               
src    └────────┘ └───────────┘
typ    └────────┘└───────────┘
doc    └────────┘ └───────────┘
txt    └────────┘ └───────────┘
par    └────────┘ └───────────┘
pid              └──────────┘
st   ─────────────────────────┘└─
106    {cases h},
id            
src     └────┘
typ     └────┘
doc     └────┘
txt     └────┘
par     └────┘
pid          
st   ─────────┘└┘
107    {cases (eq_or_mem_of_mem_cons h) with h h,
id             └───────────────────┘ 
src     └────┘ └───────────────────┘ └────────┘
typ     └────┘ └───────────────────┘└────────┘
doc     └────┘                       └────────┘
txt     └────┘                       └────────┘
par     └────┘                       └────────┘
pid                                 └───────┘
st   ──────────────────────────────────────────┘└─
108      {exact ⟨c, mem_cons_self _ _, h.symm⟩},
id                 └───────────┘      └────┘
src       └────┘  └┘└───────────┘└────┘└────┘
typ       └────┘ └┘└───────────┘└────┘└────┘
doc       └────┘  └┘             └────┘      
txt       └────┘  └┘             └────┘      
par       └────┘  └┘             └────┘      
pid              └┘             └────┘      
st   ────────────────────────────────────────┘└┘
109      {rcases ih h with ⟨a, ha₁, ha₂⟩,
id               └┘ 
src       └─────┘   └─────────────────┘
typ       └─────┘└┘└─────────────────┘
doc       └─────┘   └─────────────────┘
txt       └─────┘   └─────────────────┘
par       └─────┘   └─────────────────┘
pid                └─────────────────┘
st   ──────────────────────────────────┘└─
110        exact ⟨a, mem_cons_of_mem _ ha₁, ha₂⟩ }}
id                  └─────────────┘   └─┘  └─┘
src        └────┘  └┘└─────────────┘└─┘   └┘   └┘
typ        └────┘ └┘└─────────────┘└─┘└─┘└┘└─┘└┘
doc        └────┘  └┘               └─┘   └┘   └┘
txt        └────┘  └┘               └─┘   └┘   └┘
par        └────┘  └┘               └─┘   └┘   └┘
pid               └┘               └─┘   └┘   
st   ───────────────────────────────────────────┘└──
111  end
st   ──┘
112  
113  @[simp] theorem mem_map {f : α → β} {b : β} {l : list α} : b ∈ map f l ↔ ∃ a, a ∈ l ∧ f a = b :=
id                                                 └──┘       └─┘             
src                                                   └──┘         └─┘                   
typ                                                └──┘       └─┘             
doc    └──┘
114  ⟨exists_of_mem_map, λ ⟨a, la, h⟩, by rw [← h]; exact mem_map_of_mem f la⟩
id    └───────────────┘                                 └────────────┘  └┘
src   └───────────────┘                   └────┘   └────┘└────────────┘ 
typ   └───────────────┘                  └────┘  └────┘└────────────┘└┘
doc                                       └────┘   └────┘               
txt                                       └────┘   └────┘               
par                                       └────┘   └────┘               
pid                                         └──┘                       
st                                       └──────┘└─────────────────────────┘
115  
116  @[simp] theorem mem_map_of_inj {f : α → β} (H : injective f) {a : α} {l : list α} :
id                                                 └───────┘               └──┘ 
src                                                  └───────┘                 └──┘
typ                                                └───────┘               └──┘ 
doc    └──┘
117    f a ∈ map f l ↔ a ∈ l :=
id        └─┘      
src         └─┘        
typ       └─┘      
118  ⟨λ m, let ⟨a', m', e⟩ := exists_of_mem_map m in H e ▸ m', mem_map_of_mem _⟩
id        └─┘      └┘       └───────────────┘             └────────────┘
src                           └───────────────┘               └────────────┘
typ       └─┘      └┘       └───────────────┘             └────────────┘
119  
120  @[simp] lemma map_eq_nil {f : α → β} {l : list α} : list.map f l = [] ↔ l = [] :=
id                                           └──┘     └──────┘    └┘    └┘
src                                            └──┘      └──────┘      └┘     └┘
typ                                          └──┘     └──────┘    └┘    └┘
doc    └──┘
121  ⟨by cases l; simp only [forall_prop_of_true, map, forall_prop_of_false, not_false_iff],
id                          └─────────────────┘  └─┘  └──────────────────┘  └───────────┘
src      └────┘   └─────────┘└─────────────────┘└┘└─┘└┘└──────────────────┘└┘└───────────┘
typ      └────┘  └─────────┘└─────────────────┘└┘└─┘└┘└──────────────────┘└┘└───────────┘
doc      └────┘   └─────────┘                   └┘   └┘                    └┘             
txt      └────┘   └─────────┘                   └┘   └┘                    └┘             
par      └────┘   └─────────┘                   └┘   └┘                    └┘             
pid                  └──┘└┘                   └┘   └┘                    └┘             
st      └─────────────────────────────────────────────────────────────────────────────────┘
122    λ h, h.symm ▸ rfl⟩
id         └───┘  └─┘
src          └───┘  └─┘
typ        └───┘  └─┘
123  
124  @[simp] theorem mem_join {a : α} : ∀ {L : list (list α)}, a ∈ join L ↔ ∃ l, l ∈ L ∧ a ∈ l
id                                           └──┘  └──┘       └──┘           
src                                            └──┘  └──┘         └──┘               
typ                                          └──┘  └──┘       └──┘           
doc    └──┘
125  | []       := ⟨false.elim, λ⟨_, h, _⟩, false.elim h⟩
id     └┘           └────────┘            └────────┘
src    └┘           └────────┘              └────────┘
typ    └┘           └────────┘            └────────┘
126  | (c :: L) := by simp only [join, mem_append, @mem_join L, mem_cons_iff, or_and_distrib_right, exists_or_distrib, exists_eq_left]
id        └┘                     └──┘  └────────┘   └──────┘   └──────────┘  └──────────────────┘  └───────────────┘  └────────────┘
src       └┘          └─────────┘└──┘└┘└────────┘└┘          └┘└──────────┘└┘└──────────────────┘└┘└───────────────┘└┘└────────────┘└─
typ       └┘          └─────────┘└──┘└┘└────────┘└┘ └──────┘└┘└──────────┘└┘└──────────────────┘└┘└───────────────┘└┘└────────────┘└─
doc                   └─────────┘    └┘          └┘          └┘            └┘                    └┘                 └┘              └─
txt                   └─────────┘    └┘          └┘          └┘            └┘                    └┘                 └┘              └─
par                   └─────────┘    └┘          └┘          └┘            └┘                    └┘                 └┘              └─
pid                       └──┘└┘    └┘          └┘          └┘            └┘                    └┘                 └┘              
st                   └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
127  
src  
typ  
doc  
txt  
par  
pid  
st   
128  theorem exists_of_mem_join {a : α} {L : list (list α)} : a ∈ join L → ∃ l, l ∈ L ∧ a ∈ l :=
id                                          └──┘  └──┘        └──┘            
src                                          └──┘  └──┘          └──┘                
typ                                         └──┘  └──┘        └──┘            
129  mem_join.1
id   └──────┘
src  └──────┘
typ  └──────┘
130  
131  theorem mem_join_of_mem {a : α} {L : list (list α)} {l} (lL : l ∈ L) (al : a ∈ l) : a ∈ join L :=
id                                       └──┘  └──┘                                └──┘ 
src                                       └──┘  └──┘                                      └──┘
typ                                      └──┘  └──┘                                └──┘ 
132  mem_join.2 ⟨l, lL, al⟩
id   └──────┘     └┘  └┘
src  └──────┘
typ  └──────┘     └┘  └┘
133  
134  @[simp] theorem mem_bind {b : β} {l : list α} {f : α → list β} : b ∈ list.bind l f ↔ ∃ a ∈ l, b ∈ f a :=
id                                        └──┘           └──┘       └───────┘            
src                                        └──┘             └──┘         └───────┘               
typ                                       └──┘           └──┘       └───────┘            
doc    └──┘
135  iff.trans mem_join
id   └───────┘ └──────┘
src  └───────┘ └──────┘
typ  └───────┘ └──────┘
136    ⟨λ ⟨l', h1, h2⟩, let ⟨a, al, fa⟩ := exists_of_mem_map h1 in ⟨a, al, fa.symm ▸ h2⟩,
id            └┘  └┘   └─┘    └┘  └┘     └───────────────┘                 └───┘ 
src                                        └───────────────┘                 └───┘ 
typ           └┘  └┘   └─┘    └┘  └┘     └───────────────┘                 └───┘ 
137    λ ⟨a, al, bfa⟩, ⟨f a, mem_map_of_mem _ al, bfa⟩⟩
id         └┘  └─┘        └────────────┘
src                          └────────────┘
typ        └┘  └─┘        └────────────┘
138  
139  theorem exists_of_mem_bind {b : β} {l : list α} {f : α → list β} : b ∈ list.bind l f → ∃ a ∈ l, b ∈ f a :=
id                                          └──┘           └──┘       └───────┘             
src                                          └──┘             └──┘         └───────┘                
typ                                         └──┘           └──┘       └───────┘             
140  mem_bind.1
id   └──────┘
src  └──────┘
typ  └──────┘
141  
142  theorem mem_bind_of_mem {b : β} {l : list α} {f : α → list β} {a} (al : a ∈ l) (h : b ∈ f a) : b ∈ list.bind l f :=
id                                       └──┘           └──┘                               └───────┘  
src                                       └──┘             └──┘                                      └───────┘
typ                                      └──┘           └──┘                               └───────┘  
143  mem_bind.2 ⟨a, al, h⟩
id   └──────┘     └┘  
src  └──────┘
typ  └──────┘     └┘  
144  
145  lemma bind_map {g : α → list β} {f : β → γ} :
id                          └──┘           
src                          └──┘
typ                         └──┘           
146    ∀(l : list α), list.map f (l.bind g) = l.bind (λa, (g a).map f)
id          └──┘    └──────┘   └───┘    └───┘        └─┘  
src          └──┘     └──────┘     └───┘      └───┘           └─┘
typ         └──┘    └──────┘   └───┘    └───┘        └─┘  
147  | [] := rfl
id     └┘    └─┘
src    └┘    └─┘
typ    └┘    └─┘
148  | (a::l) := by simp only [cons_bind, map_append, bind_map l]
id       └┘                    └───────┘  └────────┘  └──────┘ 
src      └┘         └─────────┘└───────┘└┘└────────┘└┘         └─
typ      └┘         └─────────┘└───────┘└┘└────────┘└┘└──────┘└─
doc                 └─────────┘         └┘          └┘         └─
txt                 └─────────┘         └┘          └┘         └─
par                 └─────────┘         └┘          └┘         └─
pid                     └──┘└┘         └┘          └┘         
st                 └──────────────────────────────────────────────
149  
src  
typ  
doc  
txt  
par  
pid  
st   
150  /- length -/
src  ─────────────
typ  ─────────────
doc  ─────────────
txt  ─────────────
par  ─────────────
pid  ─────────────
st   ─────────────
151  
src  
typ  
doc  
txt  
par  
pid  
st   
152  theorem length_eq_zero {l : list α} : length l = 0 ↔ l = [] :=
id                               └──┘     └────┘        └┘
src                              └──┘      └────┘          └┘
typ                              └──┘     └────┘        └┘
153  ⟨eq_nil_of_length_eq_zero, λ h, h.symm ▸ rfl⟩
id    └──────────────────────┘      └───┘  └─┘
src   └──────────────────────┘        └───┘  └─┘
typ   └──────────────────────┘      └───┘  └─┘
154  
155  theorem length_pos_of_mem {a : α} : ∀ {l : list α}, a ∈ l → 0 < length l
id                                            └──┘            └────┘ 
src                                             └──┘               └────┘
typ                                           └──┘            └────┘ 
156  | (b::l) _ := zero_lt_succ _
id       └┘        └──────────┘
src      └┘        └──────────┘
typ      └┘        └──────────┘
157  
158  theorem exists_mem_of_length_pos : ∀ {l : list α}, 0 < length l → ∃ a, a ∈ l
id                                            └──┘       └────┘        
src                                            └──┘        └────┘          
typ                                           └──┘       └────┘        
159  | (b::l) _ := ⟨b, mem_cons_self _ _⟩
id      └┘            └───────────┘
src      └┘            └───────────┘
typ     └┘            └───────────┘
160  
161  theorem length_pos_iff_exists_mem {l : list α} : 0 < length l ↔ ∃ a, a ∈ l :=
id                                          └──┘        └────┘       
src                                         └──┘         └────┘         
typ                                         └──┘        └────┘       
162  ⟨exists_mem_of_length_pos, λ ⟨a, h⟩, length_pos_of_mem h⟩
id    └──────────────────────┘          └───────────────┘
src   └──────────────────────┘            └───────────────┘
typ   └──────────────────────┘          └───────────────┘
163  
164  theorem ne_nil_of_length_pos {l : list α} : 0 < length l → l ≠ [] :=
id                                     └──┘        └────┘      └┘
src                                    └──┘         └────┘        └┘
typ                                    └──┘        └────┘      └┘
165  λ h1 h2, lt_irrefl 0 ((length_eq_zero.2 h2).subst h1)
id     └┘ └┘  └───────┘     └────────────┘  └┘ └───┘  └┘
src           └───────┘     └────────────┘     └───┘
typ    └┘ └┘  └───────┘     └────────────┘  └┘ └───┘  └┘
166  
167  theorem length_pos_of_ne_nil {l : list α} : l ≠ [] → 0 < length l :=
id                                     └──┘       └┘      └────┘ 
src                                    └──┘         └┘      └────┘
typ                                    └──┘       └┘      └────┘ 
168  λ h, pos_iff_ne_zero.2 $ λ h0, h $ length_eq_zero.1 h0
id       └─────────────┘      └┘     └────────────┘  └┘
src       └─────────────┘              └────────────┘
typ      └─────────────┘      └┘     └────────────┘  └┘
169  
170  theorem length_pos_iff_ne_nil {l : list α} : 0 < length l ↔ l ≠ [] :=
id                                      └──┘        └────┘     └┘
src                                     └──┘         └────┘       └┘
typ                                     └──┘        └────┘     └┘
171  ⟨ne_nil_of_length_pos, length_pos_of_ne_nil⟩
id    └──────────────────┘  └──────────────────┘
src   └──────────────────┘  └──────────────────┘
typ   └──────────────────┘  └──────────────────┘
172  
173  theorem length_eq_one {l : list α} : length l = 1 ↔ ∃ a, l = [a] :=
id                              └──┘     └────┘          
src                             └──┘      └────┘              
typ                             └──┘     └────┘          
174  ⟨match l with [a], _ := ⟨a, rfl⟩ end, λ ⟨a, e⟩, e.symm ▸ rfl⟩
id                           └─┘                └───┘  └─┘
src                            └─┘                  └───┘  └─┘
typ                          └─┘                └───┘  └─┘
175  
176  lemma exists_of_length_succ {n} :
177    ∀ l : list α, l.length = n + 1 → ∃ h t, l = h :: t
id          └──┘   └─────┘              └┘ 
src          └──┘     └─────┘                   └┘
typ         └──┘   └─────┘              └┘ 
178  | [] H := absurd H.symm $ succ_ne_zero n
id     └┘     └────┘  └───┘   └──────────┘ 
src    └┘      └────┘  └───┘   └──────────┘
typ    └┘     └────┘  └───┘   └──────────┘ 
179  | (h :: t) H := ⟨h, t, rfl⟩
id       └┘               └─┘
src       └┘                └─┘
typ      └┘               └─┘
180  
181  lemma injective_length_iff : injective (list.length : list α → ℕ) ↔ subsingleton α :=
id                                └───────┘  └─────────┘   └──┘       └──────────┘ 
src                               └───────┘  └─────────┘   └──┘        └──────────┘
typ                               └───────┘  └─────────┘   └──┘       └──────────┘ 
182  begin
st   └─────
183    split,
src    └───┘
typ    └───┘
doc    └───┘
txt    └───┘
par    └───┘
st   ──────┘└─
184    { intro h, refine ⟨λ x y, _⟩, suffices : [x] = [y], { simpa using this }, apply h, refl },
id                                                                  └──┘
src      └─────┘  └─────┘  └──────┘  └─────────┘        └──────────┘       └────┘   └───┘
typ      └─────┘  └─────┘  └──────┘  └─────────┘      └──────────┘└──┘   └────┘   └───┘
doc      └─────┘  └─────┘  └──────┘  └─────────┘           └──────────┘       └────┘   └───┘
txt      └─────┘  └─────┘  └──────┘  └─────────┘           └──────────┘       └────┘   └───┘
par      └─────┘  └─────┘  └──────┘  └─────────┘           └──────────┘       └────┘   └───┘
pid           └┘          └──────┘  └───────┘└┘                └────┘                   
st   ───┘└─────┘└─────────────────┘└────────────────────┘└──┘└───────────────┘└┘└──────┘└─────┘└┘
185    { intros hα l1 l2 hl, induction l1 generalizing l2; cases l2,
id                                     └┘                        └┘
src      └────────────────┘  └────────┘  └──────────────┘  └────┘
typ      └────────────────┘  └────────┘└┘└──────────────┘  └────┘└┘
doc      └────────────────┘  └────────┘  └──────────────┘  └────┘
txt      └────────────────┘  └────────┘  └──────────────┘  └────┘
par      └────────────────┘  └────────┘  └──────────────┘  └────┘
pid            └──────────┘             └─────────────┘       
st   ─────────────────────┘└──────────────────────────────────────┘└─
186      { refl }, { cases hl }, { cases hl },
id                         └┘            └┘
src        └───┘     └────┘       └────┘  
typ        └───┘     └────┘└┘     └────┘└┘
doc        └───┘     └────┘       └────┘  
txt        └───┘     └────┘       └────┘  
par        └───┘     └────┘       └────┘  
pid                                    
st   ─────┘└───┘└┘└─┘└───────┘└┘└─┘└───────┘└┘
187      congr, exactI subsingleton.elim _ _, apply l1_ih, simpa using hl }
id                     └───────────────┘                               └┘
src      └───┘  └─────┘└───────────────┘└──┘  └────┘       └──────────┘  
typ      └───┘  └─────┘└───────────────┘└──┘  └────┘       └──────────┘└┘
doc             └─────┘                 └──┘  └────┘       └──────────┘  
txt      └───┘  └─────┘                 └──┘  └────┘       └──────────┘  
par      └───┘  └─────┘                 └──┘  └────┘       └──────────┘  
pid                                    └──┘                   └────┘  
st   ────────┘└────────────────────────────┘└───────────┘└───────────────┘└─
188  end
st   ──┘
189  
190  lemma injective_length [subsingleton α] : injective (length : list α → ℕ) :=
id                           └──────────┘     └───────┘  └────┘   └──┘    
src                          └──────────┘      └───────┘  └────┘   └──┘     
typ                          └──────────┘     └───────┘  └────┘   └──┘    
191  injective_length_iff.mpr $ by apply_instance
id   └──────────────────┘└──┘
src  └──────────────────┘└──┘      └──────────────
typ  └──────────────────┘└──┘      └──────────────
doc                                └──────────────
txt                                └──────────────
par                                └──────────────
pid                                              
st                                └───────────────
192  
src  
typ  
doc  
txt  
par  
pid  
st   
193  /- set-theoretic notation of lists -/
src  ──────────────────────────────────────
typ  ──────────────────────────────────────
doc  ──────────────────────────────────────
txt  ──────────────────────────────────────
par  ──────────────────────────────────────
pid  ──────────────────────────────────────
st   ──────────────────────────────────────
194  
src  
typ  
doc  
txt  
par  
pid  
st   
195  lemma empty_eq : (∅ : list α) = [] := by refl
id                        └──┘    └┘
src                       └──┘     └┘       └───┘
typ                       └──┘    └┘       └───┘
doc                                           └───┘
txt                                           └───┘
par                                           └───┘
pid                                               
st                                           └────┘
196  lemma singleton_eq [decidable_eq α] (x : α) : ({x} : list α) = [x] := by refl
id                       └──────────┘                 └──┘    
src                      └──────────┘                    └──┘             └───┘
typ                      └──────────┘                 └──┘           └───┘
doc                                                                           └───┘
txt                                                                           └───┘
par                                                                           └───┘
pid                                                                               
st                                                                           └────┘
197  lemma insert_neg [decidable_eq α] {x : α} {l : list α} (h : x ∉ l) :
id                     └──────────┘               └──┘          
src                    └──────────┘                 └──┘           
typ                    └──────────┘               └──┘          
198    has_insert.insert x l = x :: l :=
id     └───────────────┘     └┘ 
src    └───────────────┘        └┘
typ    └───────────────┘     └┘ 
199  if_neg h
id   └────┘ 
src  └────┘
typ  └────┘ 
200  lemma insert_pos [decidable_eq α] {x : α} {l : list α} (h : x ∈ l) :
id                     └──────────┘               └──┘          
src                    └──────────┘                 └──┘           
typ                    └──────────┘               └──┘          
201    has_insert.insert x l = l :=
id     └───────────────┘    
src    └───────────────┘     
typ    └───────────────┘    
202  if_pos h
id   └────┘ 
src  └────┘
typ  └────┘ 
203  lemma doubleton_eq [decidable_eq α] {x y : α} (h : x ≠ y) : ({x, y} : list α) = [y, x] :=
id                       └──────────┘                             └──┘     
src                      └──────────┘                                   └──┘        
typ                      └──────────┘                             └──┘     
204  by { rw [insert_neg, singleton_eq], show y ∉ [x], rw [mem_singleton], exact h.symm }
id            └────────┘  └──────────┘                └───────────┘         └────┘
src       └──┘└────────┘└┘└──────────┘  └───┘    └──┘└───────────┘  └────┘└────┘
typ       └──┘└────────┘└┘└──────────┘  └───┘  └──┘└───────────┘  └────┘└────┘
doc       └──┘          └┘              └───┘       └──┘               └────┘      
txt       └──┘          └┘              └───┘       └──┘               └────┘      
par       └──┘          └┘              └───┘       └──┘               └────┘      
pid         └┘          └┘              └───┘         └┘                          
st     └───────────────┘└────────────┘└─────────────┘└─────────────────┘└──────────────┘└┘
205  
206  /- bounded quantifiers over lists -/
207  
208  theorem forall_mem_nil (p : α → Prop) : ∀ x ∈ @nil α, p x.
id                                                └─┘    └┘
src                                                └─┘
typ                                               └─┘    └┘
209  
210  @[simp] theorem forall_mem_cons' {p : α → Prop} {a : α} {l : list α} :
id                                                              └──┘ 
src                                                               └──┘
typ                                                             └──┘ 
doc    └──┘
211    (∀ (x : α), x = a ∨ x ∈ l → p x) ↔ p a ∧ ∀ x ∈ l, p x :=
id                                        
src                                       
typ                                       
212  by simp only [or_imp_distrib, forall_and_distrib, forall_eq]
id                 └────────────┘  └────────────────┘  └───────┘
src     └─────────┘└────────────┘└┘└────────────────┘└┘└───────┘└─
typ     └─────────┘└────────────┘└┘└────────────────┘└┘└───────┘└─
doc     └─────────┘              └┘                  └┘         └─
txt     └─────────┘              └┘                  └┘         └─
par     └─────────┘              └┘                  └┘         └─
pid         └──┘└┘              └┘                  └┘         
st     └──────────────────────────────────────────────────────────
213  
src  
typ  
doc  
txt  
par  
pid  
st   
214  theorem forall_mem_cons {p : α → Prop} {a : α} {l : list α} :
id                                                     └──┘ 
src                                                      └──┘
typ                                                    └──┘ 
215    (∀ x ∈ a :: l, p x) ↔ p a ∧ ∀ x ∈ l, p x :=
id            └┘                  
src             └┘              
typ           └┘                  
216  by simp only [mem_cons_iff, forall_mem_cons']
id                 └──────────┘  └──────────────┘
src     └─────────┘└──────────┘└┘└──────────────┘└─
typ     └─────────┘└──────────┘└┘└──────────────┘└─
doc     └─────────┘            └┘                └─
txt     └─────────┘            └┘                └─
par     └─────────┘            └┘                └─
pid         └──┘└┘            └┘                
st     └───────────────────────────────────────────
217  
src  
typ  
doc  
txt  
par  
pid  
st   
218  theorem forall_mem_of_forall_mem_cons {p : α → Prop} {a : α} {l : list α}
id                                                                   └──┘ 
src                                                                    └──┘
typ                                                                  └──┘ 
219      (h : ∀ x ∈ a :: l, p x) :
id                  └┘    
src                   └┘
typ                 └┘    
220    ∀ x ∈ l, p x :=
id             
typ            
221  (forall_mem_cons.1 h).2
id    └─────────────┘   
src   └─────────────┘    
typ   └─────────────┘   
222  
223  theorem forall_mem_singleton {p : α → Prop} {a : α} : (∀ x ∈ [a], p x) ↔ p a :=
id                                                                    
src                                                                       
typ                                                                   
224  by simp only [mem_singleton, forall_eq]
id                 └───────────┘  └───────┘
src     └─────────┘└───────────┘└┘└───────┘└─
typ     └─────────┘└───────────┘└┘└───────┘└─
doc     └─────────┘             └┘         └─
txt     └─────────┘             └┘         └─
par     └─────────┘             └┘         └─
pid         └──┘└┘             └┘         
st     └─────────────────────────────────────
225  
src  
typ  
doc  
txt  
par  
pid  
st   
226  theorem forall_mem_append {p : α → Prop} {l₁ l₂ : list α} :
id                                                    └──┘ 
src                                                    └──┘
typ                                                   └──┘ 
227    (∀ x ∈ l₁ ++ l₂, p x) ↔ (∀ x ∈ l₁, p x) ∧ (∀ x ∈ l₂, p x) :=
id           └┘ └┘ └┘            └┘            └┘   
src              └┘                           
typ          └┘ └┘ └┘            └┘            └┘   
228  by simp only [mem_append, or_imp_distrib, forall_and_distrib]
id                 └────────┘  └────────────┘  └────────────────┘
src     └─────────┘└────────┘└┘└────────────┘└┘└────────────────┘└─
typ     └─────────┘└────────┘└┘└────────────┘└┘└────────────────┘└─
doc     └─────────┘          └┘              └┘                  └─
txt     └─────────┘          └┘              └┘                  └─
par     └─────────┘          └┘              └┘                  └─
pid         └──┘└┘          └┘              └┘                  
st     └───────────────────────────────────────────────────────────
229  
src  
typ  
doc  
txt  
par  
pid  
st   
230  theorem not_exists_mem_nil (p : α → Prop) : ¬ ∃ x ∈ @nil α, p x.
id                                                    └─┘   └┘
src                                                     └─┘  
typ                                                   └─┘   └┘
231  
232  theorem exists_mem_cons_of {p : α → Prop} {a : α} (l : list α) (h : p a) :
id                                                        └──┘         
src                                                         └──┘
typ                                                       └──┘         
233    ∃ x ∈ a :: l, p x :=
id          └┘   
src           └┘  
typ         └┘   
234  bex.intro a (mem_cons_self _ _) h
id   └───────┘   └───────────┘      
src  └───────┘    └───────────┘
typ  └───────┘   └───────────┘      
235  
236  theorem exists_mem_cons_of_exists {p : α → Prop} {a : α} {l : list α} (h : ∃ x ∈ l, p x) :
id                                                               └──┘              
src                                                                └──┘               
typ                                                              └──┘              
237    ∃ x ∈ a :: l, p x :=
id          └┘   
src           └┘  
typ         └┘   
238  bex.elim h (λ x xl px, bex.intro x (mem_cons_of_mem _ xl) px)
id   └──────┘      └┘ └┘  └───────┘   └─────────────┘   └┘  └┘
src  └──────┘               └───────┘    └─────────────┘
typ  └──────┘      └┘ └┘  └───────┘   └─────────────┘   └┘  └┘
239  
240  theorem or_exists_of_exists_mem_cons {p : α → Prop} {a : α} {l : list α} (h : ∃ x ∈ a :: l, p x) :
id                                                                  └──┘             └┘   
src                                                                   └──┘                └┘  
typ                                                                 └──┘             └┘   
241    p a ∨ ∃ x ∈ l, p x :=
id              
src               
typ             
242  bex.elim h (λ x xal px,
id   └──────┘      └─┘ └┘
src  └──────┘
typ  └──────┘      └─┘ └┘
243    or.elim (eq_or_mem_of_mem_cons xal)
id     └─────┘  └───────────────────┘ └─┘
src    └─────┘  └───────────────────┘
typ    └─────┘  └───────────────────┘ └─┘
244      (assume : x = a, begin rw ←this, left, exact px end)
id                               └──┘              └┘
src                            └──┘      └──┘  └────┘  
typ                          └──┘└──┘  └──┘  └────┘└┘
doc                             └──┘      └──┘  └────┘  
txt                             └──┘      └──┘  └────┘  
par                             └──┘      └──┘  └────┘  
pid                               └┘                   
st                        └────────────┘└────┘└─────────┘└─┘
245      (assume : x ∈ l, or.inr (bex.intro x this px)))
id                     └────┘  └───────┘  └──┘ └┘
src                      └────┘  └───────┘
typ                    └────┘  └───────┘  └──┘ └┘
246  
247  @[simp] theorem exists_mem_cons_iff (p : α → Prop) (a : α) (l : list α) :
id                                                                 └──┘ 
src                                                                  └──┘
typ                                                                └──┘ 
doc    └──┘
248    (∃ x ∈ a :: l, p x) ↔ p a ∨ ∃ x ∈ l, p x :=
id           └┘               
src            └┘                    
typ          └┘               
249  iff.intro or_exists_of_exists_mem_cons
id   └───────┘ └──────────────────────────┘
src  └───────┘ └──────────────────────────┘
typ  └───────┘ └──────────────────────────┘
250    (assume h, or.elim h (exists_mem_cons_of l) exists_mem_cons_of_exists)
id               └─────┘   └────────────────┘   └───────────────────────┘
src               └─────┘    └────────────────┘    └───────────────────────┘
typ              └─────┘   └────────────────┘   └───────────────────────┘
251  
252  /- list subset -/
253  
254  theorem subset_def {l₁ l₂ : list α} : l₁ ⊆ l₂ ↔ ∀ ⦃a : α⦄, a ∈ l₁ → a ∈ l₂ := iff.rfl
id                               └──┘     └┘  └┘              └┘     └┘    └─────┘
src                              └──┘                                          └─────┘
typ                              └──┘     └┘  └┘              └┘     └┘    └─────┘
255  
256  theorem subset_append_of_subset_left (l l₁ l₂ : list α) : l ⊆ l₁ → l ⊆ l₁++l₂ :=
id                                                   └──┘       └┘     └┘└┘└┘
src                                                  └──┘                   └┘
typ                                                  └──┘       └┘     └┘└┘└┘
257  λ s, subset.trans s $ subset_append_left _ _
id       └──────────┘    └────────────────┘
src       └──────────┘     └────────────────┘
typ      └──────────┘    └────────────────┘
258  
259  theorem subset_append_of_subset_right (l l₁ l₂ : list α) : l ⊆ l₂ → l ⊆ l₁++l₂ :=
id                                                    └──┘       └┘     └┘└┘└┘
src                                                   └──┘                   └┘
typ                                                   └──┘       └┘     └┘└┘└┘
260  λ s, subset.trans s $ subset_append_right _ _
id       └──────────┘    └─────────────────┘
src       └──────────┘     └─────────────────┘
typ      └──────────┘    └─────────────────┘
261  
262  @[simp] theorem cons_subset {a : α} {l m : list α} :
id                                             └──┘ 
src                                             └──┘
typ                                            └──┘ 
doc    └──┘
263    a::l ⊆ m ↔ a ∈ m ∧ l ⊆ m :=
id     └┘          
src     └┘              
typ    └┘          
264  by simp only [subset_def, mem_cons_iff, or_imp_distrib, forall_and_distrib, forall_eq]
id                 └────────┘  └──────────┘  └────────────┘  └────────────────┘  └───────┘
src     └─────────┘└────────┘└┘└──────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└─
typ     └─────────┘└────────┘└┘└──────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└─
doc     └─────────┘          └┘            └┘              └┘                  └┘         └─
txt     └─────────┘          └┘            └┘              └┘                  └┘         └─
par     └─────────┘          └┘            └┘              └┘                  └┘         └─
pid         └──┘└┘          └┘            └┘              └┘                  └┘         
st     └────────────────────────────────────────────────────────────────────────────────────
265  
src  
typ  
doc  
txt  
par  
pid  
st   
266  theorem cons_subset_of_subset_of_mem {a : α} {l m : list α}
id                                                      └──┘ 
src                                                      └──┘
typ                                                     └──┘ 
267    (ainm : a ∈ m) (lsubm : l ⊆ m) : a::l ⊆ m :=
id                                └┘  
src                                    └┘  
typ                               └┘  
268  cons_subset.2 ⟨ainm, lsubm⟩
id   └─────────┘   └──┘  └───┘
src  └─────────┘
typ  └─────────┘   └──┘  └───┘
269  
270  theorem append_subset_of_subset_of_subset {l₁ l₂ l : list α} (l₁subl : l₁ ⊆ l) (l₂subl : l₂ ⊆ l) :
id                                                        └──┘             └┘              └┘  
src                                                       └──┘                                  
typ                                                       └──┘             └┘              └┘  
271    l₁ ++ l₂ ⊆ l :=
id     └┘ └┘ └┘  
src       └┘    
typ    └┘ └┘ └┘  
272  λ a h, (mem_append.1 h).elim (@l₁subl _) (@l₂subl _)
id         └────────┘   └──┘    └────┘      └────┘
src          └────────┘    └──┘
typ        └────────┘   └──┘    └────┘      └────┘
273  
274  @[simp] theorem append_subset_iff {l₁ l₂ l : list α} :
id                                                └──┘ 
src                                               └──┘
typ                                               └──┘ 
doc    └──┘
275    l₁ ++ l₂ ⊆ l ↔ l₁ ⊆ l ∧ l₂ ⊆ l :=
id     └┘ └┘ └┘    └┘    └┘  
src       └┘                  
typ    └┘ └┘ └┘    └┘    └┘  
276  begin
st   └─────
277    split,
src    └───┘
typ    └───┘
doc    └───┘
txt    └───┘
par    └───┘
st   ──────┘└─
278    { intro h, simp only [subset_def] at *, split; intros; simp* },
id                           └────────┘
src      └─────┘  └─────────┘└────────┘└────┘  └───┘  └────┘  └────┘
typ      └─────┘  └─────────┘└────────┘└────┘  └───┘  └────┘  └────┘
doc      └─────┘  └─────────┘          └────┘  └───┘  └────┘  └────┘
txt      └─────┘  └─────────┘          └────┘  └───┘  └────┘  └────┘
par      └─────┘  └─────────┘          └────┘  └───┘  └────┘  └────┘
pid           └┘      └──┘└┘          └──┘                     
st   ───┘└─────┘└───────────────────────────┘└─────────────────────┘└┘
279    { rintro ⟨h1, h2⟩, apply append_subset_of_subset_of_subset h1 h2 }
id                              └───────────────────────────────┘ └┘ └┘
src      └─────────────┘  └────┘└───────────────────────────────┘    
typ      └─────────────┘  └────┘└───────────────────────────────┘└┘└┘
doc      └─────────────┘  └────┘                                     
txt      └─────────────┘  └────┘                                     
par      └─────────────┘  └────┘                                     
pid            └───────┘                                            
st   ──────────────────┘└──────────────────────────────────────────────┘└─
280  end
st   ──┘
281  
282  theorem eq_nil_of_subset_nil : ∀ {l : list α}, l ⊆ [] → l = []
id                                        └──┘      └┘     └┘
src                                        └──┘        └┘      └┘
typ                                       └──┘      └┘     └┘
283  | []     s := rfl
id     └┘          └─┘
src    └┘          └─┘
typ    └┘          └─┘
284  | (a::l) s := false.elim $ s $ mem_cons_self a l
id      └┘      └────────┘       └───────────┘
src      └┘        └────────┘       └───────────┘
typ     └┘      └────────┘       └───────────┘
285  
286  theorem eq_nil_iff_forall_not_mem {l : list α} : l = [] ↔ ∀ a, a ∉ l :=
id                                          └──┘       └┘        
src                                         └──┘         └┘         
typ                                         └──┘       └┘        
287  show l = [] ↔ l ⊆ [], from ⟨λ e, e ▸ subset.refl _, eq_nil_of_subset_nil⟩
id          └┘    └┘              └─────────┘    └──────────────────┘
src          └┘     └┘                └─────────┘    └──────────────────┘
typ         └┘    └┘              └─────────┘    └──────────────────┘
288  
289  theorem map_subset {l₁ l₂ : list α} (f : α → β) (H : l₁ ⊆ l₂) : map f l₁ ⊆ map f l₂ :=
id                               └──┘                  └┘  └┘    └─┘  └┘  └─┘  └┘
src                              └──┘                               └─┘       └─┘
typ                              └──┘                  └┘  └┘    └─┘  └┘  └─┘  └┘
290  λ x, by simp only [mem_map, not_and, exists_imp_distrib, and_imp]; exact λ a h e, ⟨a, H h, e⟩
id                     └─────┘  └─────┘  └────────────────┘  └─────┘                      
src          └─────────┘└─────┘└┘└─────┘└┘└────────────────┘└┘└─────┘  └────┘ └──────┘  └┘  └┘ └─
typ         └─────────┘└─────┘└┘└─────┘└┘└────────────────┘└┘└─────┘  └────┘ └──────┘  └┘ └┘ └─
doc          └─────────┘       └┘       └┘                  └┘         └────┘ └──────┘  └┘  └┘ └─
txt          └─────────┘       └┘       └┘                  └┘         └────┘ └──────┘  └┘  └┘ └─
par          └─────────┘       └┘       └┘                  └┘         └────┘ └──────┘  └┘  └┘ └─
pid              └──┘└┘       └┘       └┘                  └┘               └──────┘  └┘  └┘ 
st          └──────────────────────────────────────────────────────────────────────────────────────
291  
src  
typ  
doc  
txt  
par  
pid  
st   
292  theorem map_subset_iff {l₁ l₂ : list α} (f : α → β) (h : injective f) : map f l₁ ⊆ map f l₂ ↔ l₁ ⊆ l₂ :=
id                                   └──┘                  └───────┘     └─┘  └┘  └─┘  └┘  └┘  └┘
src                                  └──┘                     └───────┘      └─┘       └─┘          
typ                                  └──┘                  └───────┘     └─┘  └┘  └─┘  └┘  └┘  └┘
293  begin
st   └─────
294    refine ⟨_, map_subset f⟩, intros h2 x hx,
id                └────────┘ 
src    └─────┘ └─┘└────────┘   └────────────┘
typ    └─────┘ └─┘└────────┘  └────────────┘
doc    └─────┘ └─┘             └────────────┘
txt    └─────┘ └─┘             └────────────┘
par    └─────┘ └─┘             └────────────┘
pid           └─┘                   └──────┘
st   ─────────────────────────┘└──────────────┘└─
295    rcases mem_map.1 (h2 (mem_map_of_mem f hx)) with ⟨x', hx', hxx'⟩,
id            └─────┘    └┘  └────────────┘  └┘
src    └─────┘└─────┘└─┘    └────────────┘   └─────────────────────┘
typ    └─────┘└─────┘└─┘ └┘ └────────────┘└┘└─────────────────────┘
doc    └─────┘       └─┘                     └─────────────────────┘
txt    └─────┘       └─┘                     └─────────────────────┘
par    └─────┘       └─┘                     └─────────────────────┘
pid                 └─┘                     └─────────────────────┘
st   ─────────────────────────────────────────────────────────────────┘└─
296    cases h hxx', exact hx'
id            └──┘        └─┘
src    └────┘       └────┘   
typ    └────┘└──┘  └────┘└─┘
doc    └────┘       └────┘   
txt    └────┘       └────┘   
par    └────┘       └────┘   
pid                        
st   ─────────────┘└──────────┘
297  end
st   └─┘
298  
299  /- append -/
300  
301  lemma append_eq_has_append {L₁ L₂ : list α} : list.append L₁ L₂ = L₁ ++ L₂ := rfl
id                                       └──┘     └─────────┘ └┘ └┘  └┘ └┘ └┘    └─┘
src                                      └──┘      └─────────┘           └┘       └─┘
typ                                      └──┘     └─────────┘ └┘ └┘  └┘ └┘ └┘    └─┘
302  
303  theorem append_ne_nil_of_ne_nil_left (s t : list α) : s ≠ [] → s ++ t ≠ [] :=
id                                               └──┘       └┘    └┘   └┘
src                                              └──┘         └┘     └┘    └┘
typ                                              └──┘       └┘    └┘   └┘
304  by induction s; intros; contradiction
id                
src     └────────┘   └────┘  └─────────────
typ     └────────┘  └────┘  └─────────────
doc     └────────┘   └────┘  └─────────────
txt     └────────┘   └────┘  └─────────────
par     └────────┘   └────┘  └─────────────
pid                                      
st     └───────────────────────────────────
305  
src  
typ  
doc  
txt  
par  
pid  
st   
306  theorem append_ne_nil_of_ne_nil_right (s t : list α) : t ≠ [] → s ++ t ≠ [] :=
id                                                └──┘       └┘    └┘   └┘
src                                               └──┘         └┘     └┘    └┘
typ                                               └──┘       └┘    └┘   └┘
307  by induction s; intros; contradiction
id                
src     └────────┘   └────┘  └─────────────
typ     └────────┘  └────┘  └─────────────
doc     └────────┘   └────┘  └─────────────
txt     └────────┘   └────┘  └─────────────
par     └────────┘   └────┘  └─────────────
pid                                      
st     └───────────────────────────────────
308  
src  
typ  
doc  
txt  
par  
pid  
st   
309  theorem append_foldl (f : α → β → α) (a : α) (s t : list β) : foldl f a (s ++ t) = foldl f (foldl f a s) t :=
id                                                   └──┘     └───┘     └┘    └───┘   └───┘     
src                                                      └──┘      └───┘        └┘     └───┘    └───┘
typ                                                  └──┘     └───┘     └┘    └───┘   └───┘     
310  by {induction s with b s H generalizing a, refl, simp only [foldl, cons_append], rw H _}
id                                                              └───┘  └─────────┘      
src      └────────┘ └────────────────────────┘  └──┘  └─────────┘└───┘└┘└─────────┘  └─┘ └┘
typ      └────────┘└────────────────────────┘  └──┘  └─────────┘└───┘└┘└─────────┘  └─┘└┘
doc      └────────┘ └────────────────────────┘  └──┘  └─────────┘     └┘             └─┘ └┘
txt      └────────┘ └────────────────────────┘  └──┘  └─────────┘     └┘             └─┘ └┘
par      └────────┘ └────────────────────────┘  └──┘  └─────────┘     └┘             └─┘ └┘
pid                └────────┘└─────────────┘            └──┘└┘     └┘                └┘
st     └─────────────────────────────────────┘└────┘└──────────────────────────────┘└──────┘└┘
311  
312  theorem append_foldr (f : α → β → β) (a : β) (s t : list α) : foldr f a (s ++ t) = foldr f (foldr f a t) s :=
id                                                   └──┘     └───┘     └┘    └───┘   └───┘     
src                                                      └──┘      └───┘        └┘     └───┘    └───┘
typ                                                  └──┘     └───┘     └┘    └───┘   └───┘     
313  by {induction s with b s H generalizing a, refl, simp only [foldr, cons_append], rw H _}
id                                                              └───┘  └─────────┘      
src      └────────┘ └────────────────────────┘  └──┘  └─────────┘└───┘└┘└─────────┘  └─┘ └┘
typ      └────────┘└────────────────────────┘  └──┘  └─────────┘└───┘└┘└─────────┘  └─┘└┘
doc      └────────┘ └────────────────────────┘  └──┘  └─────────┘     └┘             └─┘ └┘
txt      └────────┘ └────────────────────────┘  └──┘  └─────────┘     └┘             └─┘ └┘
par      └────────┘ └────────────────────────┘  └──┘  └─────────┘     └┘             └─┘ └┘
pid                └────────┘└─────────────┘            └──┘└┘     └┘                └┘
st     └─────────────────────────────────────┘└────┘└──────────────────────────────┘└──────┘└┘
314  
315  @[simp] lemma append_eq_nil {p q : list α} : (p ++ q) = [] ↔ p = [] ∧ q = [] :=
id                                      └──┘       └┘    └┘    └┘    └┘
src                                     └──┘         └┘     └┘     └┘     └┘
typ                                     └──┘       └┘    └┘    └┘    └┘
doc    └──┘
316  by cases p; simp only [nil_append, cons_append, eq_self_iff_true, true_and, false_and]
id                         └────────┘  └─────────┘  └──────────────┘  └──────┘  └───────┘
src     └────┘   └─────────┘└────────┘└┘└─────────┘└┘└──────────────┘└┘└──────┘└┘└───────┘└─
typ     └────┘  └─────────┘└────────┘└┘└─────────┘└┘└──────────────┘└┘└──────┘└┘└───────┘└─
doc     └────┘   └─────────┘          └┘           └┘                └┘        └┘         └─
txt     └────┘   └─────────┘          └┘           └┘                └┘        └┘         └─
par     └────┘   └─────────┘          └┘           └┘                └┘        └┘         └─
pid                 └──┘└┘          └┘           └┘                └┘        └┘         
st     └────────────────────────────────────────────────────────────────────────────────────
317  
src  
typ  
doc  
txt  
par  
pid  
st   
318  @[simp] lemma nil_eq_append_iff {a b : list α} : [] = a ++ b ↔ a = [] ∧ b = [] :=
id                                          └──┘     └┘   └┘     └┘    └┘
src                                         └──┘      └┘    └┘       └┘     └┘
typ                                         └──┘     └┘   └┘     └┘    └┘
doc    └──┘
319  by rw [eq_comm, append_eq_nil]
id          └─────┘  └───────────┘
src     └──┘└─────┘└┘└───────────┘└─
typ     └──┘└─────┘└┘└───────────┘└─
doc     └──┘       └┘             └─
txt     └──┘       └┘             └─
par     └──┘       └┘             └─
pid       └┘       └┘             
st     └──────────┘└─────────────┘
320  
src  
typ  
doc  
txt  
par  
pid  
st   
321  lemma append_eq_cons_iff {a b c : list α} {x : α} :
id                                     └──┘        
src                                    └──┘
typ                                    └──┘        
322    a ++ b = x :: c ↔ (a = [] ∧ b = x :: c) ∨ (∃a', a = x :: a' ∧ c = a' ++ b) :=
id      └┘    └┘      └┘     └┘     └┘    └┘ └┘    └┘ └┘ 
src      └┘      └┘        └┘       └┘              └┘           └┘
typ     └┘    └┘      └┘     └┘     └┘    └┘ └┘    └┘ └┘ 
323  by cases a; simp only [and_assoc, @eq_comm _ c, nil_append, cons_append, eq_self_iff_true,
id                         └───────┘   └─────┘     └────────┘  └─────────┘  └──────────────┘
src     └────┘   └─────────┘└───────┘└┘ └─────┘└─┘ └┘└────────┘└┘└─────────┘└┘└──────────────┘└─
typ     └────┘  └─────────┘└───────┘└┘ └─────┘└─┘└┘└────────┘└┘└─────────┘└┘└──────────────┘└─
doc     └────┘   └─────────┘         └┘        └─┘ └┘          └┘           └┘                └─
txt     └────┘   └─────────┘         └┘        └─┘ └┘          └┘           └┘                └─
par     └────┘   └─────────┘         └┘        └─┘ └┘          └┘           └┘                └─
pid                 └──┘└┘         └┘        └─┘ └┘          └┘           └┘                └─
st     └────────────────────────────────────────────────────────────────────────────────────────
324    true_and, false_and, exists_false, false_or, or_false, exists_and_distrib_left, exists_eq_left']
id     └──────┘  └───────┘  └──────────┘  └──────┘  └──────┘  └─────────────────────┘  └─────────────┘
src  ─┘└──────┘└┘└───────┘└┘└──────────┘└┘└──────┘└┘└──────┘└┘└─────────────────────┘└┘└─────────────┘└─
typ  ─┘└──────┘└┘└───────┘└┘└──────────┘└┘└──────┘└┘└──────┘└┘└─────────────────────┘└┘└─────────────┘└─
doc  ─┘        └┘         └┘            └┘        └┘        └┘                       └┘               └─
txt  ─┘        └┘         └┘            └┘        └┘        └┘                       └┘               └─
par  ─┘        └┘         └┘            └┘        └┘        └┘                       └┘               └─
pid  ─┘        └┘         └┘            └┘        └┘        └┘                       └┘               
st   ───────────────────────────────────────────────────────────────────────────────────────────────────
325  
src  
typ  
doc  
txt  
par  
pid  
st   
326  lemma cons_eq_append_iff {a b c : list α} {x : α} :
id                                     └──┘        
src                                    └──┘
typ                                    └──┘        
327    (x :: c : list α) = a ++ b ↔ (a = [] ∧ b = x :: c) ∨ (∃a', a = x :: a' ∧ c = a' ++ b) :=
id       └┘    └──┘     └┘      └┘     └┘     └┘    └┘ └┘    └┘ └┘ 
src       └┘     └──┘       └┘        └┘       └┘              └┘           └┘
typ      └┘    └──┘     └┘      └┘     └┘     └┘    └┘ └┘    └┘ └┘ 
328  by rw [eq_comm, append_eq_cons_iff]
id          └─────┘  └────────────────┘
src     └──┘└─────┘└┘└────────────────┘└─
typ     └──┘└─────┘└┘└────────────────┘└─
doc     └──┘       └┘                  └─
txt     └──┘       └┘                  └─
par     └──┘       └┘                  └─
pid       └┘       └┘                  
st     └──────────┘└──────────────────┘
329  
src  
typ  
doc  
txt  
par  
pid  
st   
330  lemma append_eq_append_iff {a b c d : list α} :
id                                         └──┘ 
src                                        └──┘
typ                                        └──┘ 
331    a ++ b = c ++ d ↔ (∃a', c = a ++ a' ∧ b = a' ++ d) ∨ (∃c', a = c ++ c' ∧ d = c' ++ b) :=
id      └┘    └┘    └┘    └┘ └┘    └┘ └┘     └┘    └┘ └┘    └┘ └┘ 
src      └┘      └┘             └┘           └┘              └┘           └┘
typ     └┘    └┘    └┘    └┘ └┘    └┘ └┘     └┘    └┘ └┘    └┘ └┘ 
332  begin
st   └─────
333    induction a generalizing c,
id               
src    └────────┘ └─────────────┘
typ    └────────┘└─────────────┘
doc    └────────┘ └─────────────┘
txt    └────────┘ └─────────────┘
par    └────────┘ └─────────────┘
pid              └────────────┘
st   ───────────────────────────┘└─
334    case nil { rw nil_append, split,
id                   └────────┘
src    └─────────┘└─┘└────────┘└┘└───┘└─
typ    └─────────┘└─┘└────────┘└┘└───┘└─
doc    └─────────┘└─┘          └┘└───┘└─
txt    └─────────┘└─┘          └┘└───┘└─
par    └─────────┘└─┘          └┘└───┘└─
pid        └──┘└───┘          └────────
st   ───────────┘└────────────┘└─────┘└─
335      { rintro rfl, left, exact ⟨_, rfl, rfl⟩ },
id                                          └─┘
src  ─────┘└────────┘└┘└──┘└┘└────┘ └─┘   └┘└─┘└┘└──
typ  ─────┘└────────┘└┘└──┘└┘└────┘ └─┘   └┘└─┘└┘└──
doc  ─────┘└────────┘└┘└──┘└┘└────┘ └─┘   └┘   └┘└──
txt  ─────┘└────────┘└┘└──┘└┘└────┘ └─┘   └┘   └┘└──
par  ─────┘└────────┘└┘└──┘└┘└────┘ └─┘   └┘   └┘└──
pid  ─────────────────────────────┘ └─┘   └┘   └────
st   ────┘└─────────┘└────┘└────────────────────┘└─
336      { rintro (⟨a', rfl, rfl⟩ | ⟨a', H, rfl⟩), {refl}, {rw [← append_assoc, ← H], refl} } },
id                                                                └──────────┘    
src  ─────┘└────────────────────────────────────┘└─┘└──┘└──┘└────┘└──────────┘└──┘ └┘└──┘└───┘
typ  ─────┘└────────────────────────────────────┘└─┘└──┘└──┘└────┘└──────────┘└──┘└┘└──┘└───┘
doc  ─────┘└────────────────────────────────────┘└─┘└──┘└──┘└────┘            └──┘ └┘└──┘└───┘
txt  ─────┘└────────────────────────────────────┘└─┘└──┘└──┘└────┘            └──┘ └┘└──┘└───┘
par  ─────┘└────────────────────────────────────┘└─┘└──┘└──┘└────┘            └──┘ └┘└──┘└───┘
pid  ────────────────────────────────────────────────────────────┘            └──┘ └──────────┘
st   ───────────────────────────────────────────┘└─────┘└───────────────────┘└───┘└─────┘└────┘
337    case cons : a as ih {
src    └─────────────────────
typ    └─────────────────────
doc    └─────────────────────
txt    └─────────────────────
par    └─────────────────────
pid        └───┘└────────┘└──
st   ──────────────────────┘
338      cases c,
id             
src  ───┘└────┘ └─
typ  ───┘└────┘└─
doc  ───┘└────┘ └─
txt  ───┘└────┘ └─
par  ───┘└────┘ └─
pid  ─────────┘ └─
st   ──────────┘└─
339      { simp only [cons_append, nil_append, false_and, exists_false, false_or, exists_eq_left'], exact eq_comm },
id                    └─────────┘  └────────┘  └───────┘  └──────────┘  └──────┘  └─────────────┘         └─────┘
src  ─────┘└─────────┘└─────────┘└┘└────────┘└┘└───────┘└┘└──────────┘└┘└──────┘└┘└─────────────┘└┘└────┘└─────┘└──
typ  ─────┘└─────────┘└─────────┘└┘└────────┘└┘└───────┘└┘└──────────┘└┘└──────┘└┘└─────────────┘└┘└────┘└─────┘└──
doc  ─────┘└─────────┘           └┘          └┘         └┘            └┘        └┘               └┘└────┘       └──
txt  ─────┘└─────────┘           └┘          └┘         └┘            └┘        └┘               └┘└────┘       └──
par  ─────┘└─────────┘           └┘          └┘         └┘            └┘        └┘               └┘└────┘       └──
pid  ────────────────┘           └┘          └┘         └┘            └┘        └┘               └───────┘       └───
st   ────┘└──────────────────────────────────────────────────────────────────────────────────────┘└──────────────┘└─
340      { simp only [cons_append, @eq_comm _ a, ih, and_assoc, and_or_distrib_left, exists_and_distrib_left] } }
id                    └─────────┘   └─────┘         └───────┘  └─────────────────┘  └─────────────────────┘
src  ─────┘└─────────┘└─────────┘└┘ └─────┘└─┘ └┘  └┘└───────┘└┘└─────────────────┘└┘└─────────────────────┘└┘└──┘
typ  ─────┘└─────────┘└─────────┘└┘ └─────┘└─┘└┘└┘└┘└───────┘└┘└─────────────────┘└┘└─────────────────────┘└┘└──┘
doc  ─────┘└─────────┘           └┘        └─┘ └┘  └┘         └┘                   └┘                       └┘└──┘
txt  ─────┘└─────────┘           └┘        └─┘ └┘  └┘         └┘                   └┘                       └┘└──┘
par  ─────┘└─────────┘           └┘        └─┘ └┘  └┘         └┘                   └┘                       └┘└──┘
pid  ────────────────┘           └┘        └─┘ └┘  └┘         └┘                   └┘                       └───┘
st   ────────────────────────────────────────────────────────────────────────────────────────────────────────┘└─┘
341  end
st   └─┘
342  
343  @[simp] theorem split_at_eq_take_drop : ∀ (n : ℕ) (l : list α), split_at n l = (take n l, drop n l)
id                                                        └──┘    └──────┘    └──┘    └──┘  
src                                                        └──┘     └──────┘      └──┘      └──┘
typ                                                       └──┘    └──────┘    └──┘    └──┘  
doc    └──┘                                                          └──────┘
344  | 0        a         := rfl
id                           └─┘
src                          └─┘
typ                          └─┘
345  | (succ n) []        := rfl
id      └──┘    └┘           └─┘
src     └──┘    └┘           └─┘
typ     └──┘    └┘           └─┘
346  | (succ n) (x :: xs) := by simp only [split_at, split_at_eq_take_drop n xs, take, drop]
id      └──┘       └┘                      └──────┘  └───────────────────┘  └┘  └──┘  └──┘
src     └──┘       └┘           └─────────┘└──────┘└┘                        └┘└──┘└┘└──┘└─
typ     └──┘       └┘           └─────────┘└──────┘└┘└───────────────────┘└┘└┘└──┘└┘└──┘└─
doc                             └─────────┘└──────┘└┘                        └┘    └┘    └─
txt                             └─────────┘        └┘                        └┘    └┘    └─
par                             └─────────┘        └┘                        └┘    └┘    └─
pid                                 └──┘└┘        └┘                        └┘    └┘    
st                             └─────────────────────────────────────────────────────────────
347  
src  
typ  
doc  
txt  
par  
pid  
st   
348  @[simp] theorem take_append_drop : ∀ (n : ℕ) (l : list α), take n l ++ drop n l = l
id                                                   └──┘    └──┘   └┘ └──┘    
src                                                   └──┘     └──┘     └┘ └──┘     
typ                                                  └──┘    └──┘   └┘ └──┘    
doc    └──┘
349  | 0        a         := rfl
id                           └─┘
src                          └─┘
typ                          └─┘
350  | (succ n) []        := rfl
id      └──┘    └┘           └─┘
src     └──┘    └┘           └─┘
typ     └──┘    └┘           └─┘
351  | (succ n) (x :: xs) := congr_arg (cons x) $ take_append_drop n xs
id      └──┘     └┘ └┘     └───────┘  └──┘      └──────────────┘
src     └──┘       └┘        └───────┘  └──┘
typ     └──┘     └┘ └┘     └───────┘  └──┘      └──────────────┘
352  
353  -- TODO(Leo): cleanup proof after arith dec proc
354  theorem append_inj : ∀ {s₁ s₂ t₁ t₂ : list α}, s₁ ++ t₁ = s₂ ++ t₂ → length s₁ = length s₂ → s₁ = s₂ ∧ t₁ = t₂
id                                        └──┘    └┘ └┘ └┘  └┘ └┘ └┘   └────┘ └┘  └────┘ └┘   └┘  └┘  └┘  └┘
src                                        └──┘        └┘        └┘      └────┘     └────┘                 
typ                                       └──┘    └┘ └┘ └┘  └┘ └┘ └┘   └────┘ └┘  └────┘ └┘   └┘  └┘  └┘  └┘
355  | []      []      t₁ t₂ h hl := ⟨rfl, h⟩
id     └┘      └┘                    └─┘
src    └┘      └┘                     └─┘
typ    └┘      └┘                    └─┘
356  | (a::s₁) []      t₁ t₂ h hl := list.no_confusion $ eq_nil_of_length_eq_zero hl
id       └┘    └┘              └┘    └───────────────┘   └──────────────────────┘
src      └┘    └┘                    └───────────────┘   └──────────────────────┘
typ      └┘    └┘              └┘    └───────────────┘   └──────────────────────┘
357  | []      (b::s₂) t₁ t₂ h hl := list.no_confusion $ eq_nil_of_length_eq_zero hl.symm
id     └┘        └┘            └┘    └───────────────┘   └──────────────────────┘   └───┘
src    └┘        └┘                  └───────────────┘   └──────────────────────┘   └───┘
typ    └┘        └┘            └┘    └───────────────┘   └──────────────────────┘   └───┘
358  | (a::s₁) (b::s₂) t₁ t₂ h hl := list.no_confusion h $ λab hap,
id       └┘└┘    └┘└┘  └┘ └┘  └┘    └───────────────┘      └┘ └─┘
src      └┘      └┘                  └───────────────┘
typ      └┘└┘    └┘└┘  └┘ └┘  └┘    └───────────────┘      └┘ └─┘
359    let ⟨e1, e2⟩ := @append_inj s₁ s₂ t₁ t₂ hap (succ.inj hl) in
id     └─┘              └────────┘             └─┘  └──────┘
src                                                 └──────┘
typ    └─┘              └────────┘             └─┘  └──────┘
360    by rw [ab, e1, e2]; exact ⟨rfl, rfl⟩
id            └┘  └┘  └┘               └─┘
src       └──┘  └┘  └┘    └────┘    └┘└─┘└─
typ       └──┘└┘└┘└┘└┘└┘  └────┘    └┘└─┘└─
doc       └──┘  └┘  └┘    └────┘    └┘   └─
txt       └──┘  └┘  └┘    └────┘    └┘   └─
par       └──┘  └┘  └┘    └────┘    └┘   └─
pid         └┘  └┘  └┘             └┘   
st       └─────┘└──┘└──┘└──────────────────
361  
src  
typ  
doc  
txt  
par  
pid  
st   
362  theorem append_inj_left {s₁ s₂ t₁ t₂ : list α} (h : s₁ ++ t₁ = s₂ ++ t₂) (hl : length s₁ = length s₂) : t₁ = t₂ :=
id                                          └──┘        └┘ └┘ └┘  └┘ └┘ └┘        └────┘ └┘  └────┘ └┘    └┘  └┘
src                                         └──┘            └┘        └┘           └────┘     └────┘          
typ                                         └──┘        └┘ └┘ └┘  └┘ └┘ └┘        └────┘ └┘  └────┘ └┘    └┘  └┘
363  (append_inj h hl).right
id    └────────┘  └┘ └───┘
src   └────────┘      └───┘
typ   └────────┘  └┘ └───┘
364  
365  theorem append_inj_right {s₁ s₂ t₁ t₂ : list α} (h : s₁ ++ t₁ = s₂ ++ t₂) (hl : length s₁ = length s₂) : s₁ = s₂ :=
id                                           └──┘        └┘ └┘ └┘  └┘ └┘ └┘        └────┘ └┘  └────┘ └┘    └┘  └┘
src                                          └──┘            └┘        └┘           └────┘     └────┘          
typ                                          └──┘        └┘ └┘ └┘  └┘ └┘ └┘        └────┘ └┘  └────┘ └┘    └┘  └┘
366  (append_inj h hl).left
id    └────────┘  └┘ └──┘
src   └────────┘      └──┘
typ   └────────┘  └┘ └──┘
367  
368  theorem append_inj' {s₁ s₂ t₁ t₂ : list α} (h : s₁ ++ t₁ = s₂ ++ t₂) (hl : length t₁ = length t₂) : s₁ = s₂ ∧ t₁ = t₂ :=
id                                      └──┘        └┘ └┘ └┘  └┘ └┘ └┘        └────┘ └┘  └────┘ └┘    └┘  └┘  └┘  └┘
src                                     └──┘            └┘        └┘           └────┘     └────┘                  
typ                                     └──┘        └┘ └┘ └┘  └┘ └┘ └┘        └────┘ └┘  └────┘ └┘    └┘  └┘  └┘  └┘
369  append_inj h $ @nat.add_right_cancel _ (length t₁) _ $
id   └────────┘     └──────────────────┘    └────┘ └┘
src  └────────┘      └──────────────────┘    └────┘
typ  └────────┘     └──────────────────┘    └────┘ └┘
370  let hap := congr_arg length h in by simp only [length_append] at hap; rwa [← hl] at hap
id       └─┘    └───────┘ └────┘                   └───────────┘                 └┘
src             └───────┘ └────┘         └─────────┘└───────────┘└──────┘  └─────┘  └────────
typ      └─┘    └───────┘ └────┘        └─────────┘└───────────┘└──────┘  └─────┘└┘└────────
doc                                      └─────────┘             └──────┘  └─────┘  └────────
txt                                      └─────────┘             └──────┘  └─────┘  └────────
par                                      └─────────┘             └──────┘  └─────┘  └────────
pid                                          └──┘└┘             └────┘     └──┘  └─────┘
st                                      └──────────────────────────────────────┘└──┘└───────
371  
src  
typ  
doc  
txt  
par  
pid  
st   
372  theorem append_inj_left' {s₁ s₂ t₁ t₂ : list α} (h : s₁ ++ t₁ = s₂ ++ t₂) (hl : length t₁ = length t₂) : t₁ = t₂ :=
id                                           └──┘        └┘ └┘ └┘  └┘ └┘ └┘        └────┘ └┘  └────┘ └┘    └┘  └┘
src                                          └──┘            └┘        └┘           └────┘     └────┘          
typ                                          └──┘        └┘ └┘ └┘  └┘ └┘ └┘        └────┘ └┘  └────┘ └┘    └┘  └┘
373  (append_inj' h hl).right
id    └─────────┘  └┘ └───┘
src   └─────────┘      └───┘
typ   └─────────┘  └┘ └───┘
374  
375  theorem append_inj_right' {s₁ s₂ t₁ t₂ : list α} (h : s₁ ++ t₁ = s₂ ++ t₂) (hl : length t₁ = length t₂) : s₁ = s₂ :=
id                                            └──┘        └┘ └┘ └┘  └┘ └┘ └┘        └────┘ └┘  └────┘ └┘    └┘  └┘
src                                           └──┘            └┘        └┘           └────┘     └────┘          
typ                                           └──┘        └┘ └┘ └┘  └┘ └┘ └┘        └────┘ └┘  └────┘ └┘    └┘  └┘
376  (append_inj' h hl).left
id    └─────────┘  └┘ └──┘
src   └─────────┘      └──┘
typ   └─────────┘  └┘ └──┘
377  
378  theorem append_left_cancel {s t₁ t₂ : list α} (h : s ++ t₁ = s ++ t₂) : t₁ = t₂ :=
id                                         └──┘         └┘ └┘   └┘ └┘    └┘  └┘
src                                        └──┘           └┘       └┘          
typ                                        └──┘         └┘ └┘   └┘ └┘    └┘  └┘
379  append_inj_left h rfl
id   └─────────────┘  └─┘
src  └─────────────┘   └─┘
typ  └─────────────┘  └─┘
380  
381  theorem append_right_cancel {s₁ s₂ t : list α} (h : s₁ ++ t = s₂ ++ t) : s₁ = s₂ :=
id                                          └──┘        └┘ └┘   └┘ └┘     └┘  └┘
src                                         └──┘            └┘       └┘         
typ                                         └──┘        └┘ └┘   └┘ └┘     └┘  └┘
382  append_inj_right' h rfl
id   └───────────────┘  └─┘
src  └───────────────┘   └─┘
typ  └───────────────┘  └─┘
383  
384  theorem append_left_inj {t₁ t₂ : list α} (s) : s ++ t₁ = s ++ t₂ ↔ t₁ = t₂ :=
id                                    └──┘          └┘ └┘   └┘ └┘  └┘  └┘
src                                   └──┘            └┘       └┘        
typ                                   └──┘          └┘ └┘   └┘ └┘  └┘  └┘
385  ⟨append_left_cancel, congr_arg _⟩
id    └────────────────┘  └───────┘
src   └────────────────┘  └───────┘
typ   └────────────────┘  └───────┘
386  
387  theorem append_right_inj {s₁ s₂ : list α} (t) : s₁ ++ t = s₂ ++ t ↔ s₁ = s₂ :=
id                                     └──┘         └┘ └┘   └┘ └┘   └┘  └┘
src                                    └──┘             └┘       └┘       
typ                                    └──┘         └┘ └┘   └┘ └┘   └┘  └┘
388  ⟨append_right_cancel, congr_arg _⟩
id    └─────────────────┘  └───────┘
src   └─────────────────┘  └───────┘
typ   └─────────────────┘  └───────┘
389  
390  theorem map_eq_append_split {f : α → β} {l : list α} {s₁ s₂ : list β}
id                                              └──┘            └──┘ 
src                                               └──┘             └──┘
typ                                             └──┘            └──┘ 
391    (h : map f l = s₁ ++ s₂) : ∃ l₁ l₂, l = l₁ ++ l₂ ∧ map f l₁ = s₁ ∧ map f l₂ = s₂ :=
id          └─┘    └┘ └┘ └┘     └┘ └┘   └┘ └┘ └┘  └─┘  └┘  └┘  └─┘  └┘  └┘
src         └─┘         └┘                    └┘     └─┘           └─┘      
typ         └─┘    └┘ └┘ └┘     └┘ └┘   └┘ └┘ └┘  └─┘  └┘  └┘  └─┘  └┘  └┘
392  begin
st   └─────
393    have := h, rw [← take_append_drop (length s₁) l] at this ⊢,
id                     └──────────────┘  └────┘ └┘  
src    └──────┘   └────┘└──────────────┘ └────┘  └┘ └─────────┘
typ    └──────┘  └────┘└──────────────┘ └────┘└┘└┘└─────────┘
doc    └──────┘   └────┘                         └┘ └─────────┘
txt    └──────┘   └────┘                         └┘ └─────────┘
par    └──────┘   └────┘                         └┘ └─────────┘
pid    └───┘└─┘     └──┘                         └┘ └────────┘
st   ──────────┘└────────────────────────────────────┘└────────┘└─
394    rw map_append at this,
id        └────────┘
src    └─┘└────────┘└──────┘
typ    └─┘└────────┘└──────┘
doc    └─┘          └──────┘
txt    └─┘          └──────┘
par    └─┘          └──────┘
pid                └──────┘
st   ──────────────────────┘└─
395    refine ⟨_, _, rfl, append_inj this _⟩,
id                   └─┘  └────────┘ └──┘
src    └─────┘ └────┘└─┘└┘└────────┘    └─┘
typ    └─────┘ └────┘└─┘└┘└────────┘└──┘└─┘
doc    └─────┘ └────┘   └┘              └─┘
txt    └─────┘ └────┘   └┘              └─┘
par    └─────┘ └────┘   └┘              └─┘
pid           └────┘   └┘              └─┘
st   ──────────────────────────────────────┘└─
396    rw [length_map, length_take, min_eq_left],
id         └────────┘  └─────────┘  └─────────┘
src    └──┘└────────┘└┘└─────────┘└┘└─────────┘
typ    └──┘└────────┘└┘└─────────┘└┘└─────────┘
doc    └──┘          └┘           └┘           
txt    └──┘          └┘           └┘           
par    └──┘          └┘           └┘           
pid      └┘          └┘           └┘           
st   ───────────────┘└───────────┘└───────────┘└──
397    rw [← length_map f l, h, length_append],
id           └────────┘      └───────────┘
src    └────┘└────────┘  └┘ └┘└───────────┘
typ    └────┘└────────┘└┘└┘└───────────┘
doc    └────┘            └┘ └┘             
txt    └────┘            └┘ └┘             
par    └────┘            └┘ └┘             
pid      └──┘            └┘ └┘             
st   ─────────────────────┘└─┘└─────────────┘└──
398    apply nat.le_add_right
id           └──────────────┘
src    └────┘└──────────────┘
typ    └────┘└──────────────┘
doc    └────┘                
txt    └────┘                
par    └────┘                
pid                         
st   ────────────────────────┘
399  end
st   └─┘
400  
401  /- join -/
402  
403  attribute [simp] join
id                    └──┘
src                   └──┘
typ                   └──┘
doc             └──┘
404  
405  theorem join_eq_nil : ∀ {L : list (list α)}, join L = [] ↔ ∀ l ∈ L, l = []
id                               └──┘  └──┘     └──┘   └┘           └┘
src                               └──┘  └──┘      └──┘    └┘              └┘
typ                              └──┘  └──┘     └──┘   └┘           └┘
406  | []     := iff_of_true rfl (forall_mem_nil _)
id     └┘        └─────────┘ └─┘  └────────────┘
src    └┘        └─────────┘ └─┘  └────────────┘
typ    └┘        └─────────┘ └─┘  └────────────┘
407  | (l::L) := by simp only [join, append_eq_nil, join_eq_nil, forall_mem_cons]
id       └┘                    └──┘  └───────────┘               └─────────────┘
src      └┘         └─────────┘└──┘└┘└───────────┘└┘           └┘└─────────────┘└─
typ      └┘         └─────────┘└──┘└┘└───────────┘└┘└─────────┘└┘└─────────────┘└─
doc                 └─────────┘    └┘             └┘           └┘               └─
txt                 └─────────┘    └┘             └┘           └┘               └─
par                 └─────────┘    └┘             └┘           └┘               └─
pid                     └──┘└┘    └┘             └┘           └┘               
st                 └──────────────────────────────────────────────────────────────
408  
src  
typ  
doc  
txt  
par  
pid  
st   
409  @[simp] theorem join_append (L₁ L₂ : list (list α)) : join (L₁ ++ L₂) = join L₁ ++ join L₂ :=
id                                        └──┘  └──┘      └──┘  └┘ └┘ └┘   └──┘ └┘ └┘ └──┘ └┘
src                                       └──┘  └──┘       └──┘     └┘      └──┘    └┘ └──┘
typ                                       └──┘  └──┘      └──┘  └┘ └┘ └┘   └──┘ └┘ └┘ └──┘ └┘
doc    └──┘
410  by induction L₁; [refl, simp only [*, join, cons_append, append_assoc]]
id                └┘                      └──┘  └─────────┘  └──────────┘
src     └────────┘    └──┘  └────────────┘└──┘└┘└─────────┘└┘└──────────┘
typ     └────────┘└┘  └──┘  └────────────┘└──┘└┘└─────────┘└┘└──────────┘
doc     └────────┘     └──┘  └────────────┘    └┘           └┘            
txt     └────────┘     └──┘  └────────────┘    └┘           └┘            
par     └────────┘     └──┘  └────────────┘    └┘           └┘            
pid                             └──┘└───┘    └┘           └┘            
st     └───────────────────────────────────────────────────────────────────┘
411  
412  lemma join_join (l : list (list (list α))) : l.join.join = (l.map join).join :=
id                        └──┘  └──┘  └──┘       └────────┘   └──┘ └──┘ └──┘
src                       └──┘  └──┘  └──┘         └────────┘    └──┘ └──┘ └──┘
typ                       └──┘  └──┘  └──┘       └────────┘   └──┘ └──┘ └──┘
413  by { induction l, simp, simp [l_ih] }
id                                └──┘
src       └────────┘   └──┘  └────┘    └┘
typ       └────────┘  └──┘  └────┘└──┘└┘
doc       └────────┘   └──┘  └────┘    └┘
txt       └────────┘   └──┘  └────┘    └┘
par       └────────┘   └──┘  └────┘    └┘
pid                                 
st     └────────────┘└────┘└────────────┘└┘
414  
415  /- repeat -/
416  
417  @[simp] theorem repeat_succ (a : α) (n) : repeat a (n + 1) = a :: repeat a n := rfl
id                                            └────┘          └┘ └────┘      └─┘
src                                            └────┘             └┘ └────┘        └─┘
typ                                           └────┘          └┘ └────┘      └─┘
doc    └──┘
418  
419  theorem eq_of_mem_repeat {a b : α} : ∀ {n}, b ∈ repeat a n → b = a
id                                              └────┘       
src                                                 └────┘         
typ                                             └────┘       
420  | (n+1) h := or.elim h id $ @eq_of_mem_repeat _
id              └─────┘   └┘    └──────────────┘
src              └─────┘   └┘
typ             └─────┘   └┘    └──────────────┘
421  
422  theorem eq_repeat_of_mem {a : α} : ∀ {l : list α}, (∀ b ∈ l, b = a) → l = repeat a l.length
id                                           └──┘                    └────┘  └─────┘
src                                            └──┘                          └────┘    └─────┘
typ                                          └──┘                    └────┘  └─────┘
423  | []     H := rfl
id     └┘          └─┘
src    └┘          └─┘
typ    └┘          └─┘
424  | (b::l) H := by cases forall_mem_cons.1 H with H₁ H₂;
id       └┘                 └─────────────┘   
src      └┘           └────┘└─────────────┘└─┘ └─────────┘
typ      └┘           └────┘└─────────────┘└─┘└─────────┘
doc                   └────┘               └─┘ └─────────┘
txt                   └────┘               └─┘ └─────────┘
par                   └────┘               └─┘ └─────────┘
pid                                       └─┘ └─────────┘
st                   └──────────────────────────────────────
425    unfold length repeat; congr; [exact H₁, exact eq_repeat_of_mem H₂]
id                                        └┘        └──────────────┘ └┘
src    └──────────────────┘  └───┘  └────┘    └────┘                
typ    └──────────────────┘  └───┘  └────┘└┘  └────┘└──────────────┘└┘
doc    └──────────────────┘          └────┘    └────┘                
txt    └──────────────────┘  └───┘   └────┘    └────┘                
par    └──────────────────┘  └───┘   └────┘    └────┘                
pid          └────────────┘                                        
st   ───────────────────────────────────────────────────────────────────┘
426  
427  theorem eq_repeat' {a : α} {l : list α} : l = repeat a l.length ↔ ∀ b ∈ l, b = a :=
id                                  └──┘       └────┘  └─────┘           
src                                  └──┘         └────┘    └─────┘             
typ                                 └──┘       └────┘  └─────┘           
428  ⟨λ h, h.symm ▸ λ b, eq_of_mem_repeat, eq_repeat_of_mem⟩
id        └───┘      └──────────────┘  └──────────────┘
src         └───┘       └──────────────┘  └──────────────┘
typ       └───┘      └──────────────┘  └──────────────┘
429  
430  theorem eq_repeat {a : α} {n} {l : list α} : l = repeat a n ↔ length l = n ∧ ∀ b ∈ l, b = a :=
id                                     └──┘       └────┘    └────┘              
src                                     └──┘         └────┘      └────┘                  
typ                                    └──┘       └────┘    └────┘              
431  ⟨λ h, h.symm ▸ ⟨length_repeat _ _, λ b, eq_of_mem_repeat⟩,
id        └───┘   └───────────┘          └──────────────┘
src         └───┘   └───────────┘           └──────────────┘
typ       └───┘   └───────────┘          └──────────────┘
432   λ ⟨e, al⟩, e ▸ eq_repeat_of_mem al⟩
id        └┘      └──────────────┘
src                 └──────────────┘
typ       └┘      └──────────────┘
433  
434  theorem repeat_add (a : α) (m n) : repeat a (m + n) = repeat a m ++ repeat a n :=
id                                     └────┘        └────┘   └┘ └────┘  
src                                     └────┘           └────┘     └┘ └────┘
typ                                    └────┘        └────┘   └┘ └────┘  
435  by induction m; simp only [*, zero_add, succ_add, repeat]; split; refl
id                                └──────┘  └──────┘  └────┘
src     └────────┘   └────────────┘└──────┘└┘└──────┘└┘└────┘  └───┘  └────
typ     └────────┘  └────────────┘└──────┘└┘└──────┘└┘└────┘  └───┘  └────
doc     └────────┘   └────────────┘        └┘        └┘        └───┘  └────
txt     └────────┘   └────────────┘        └┘        └┘        └───┘  └────
par     └────────┘   └────────────┘        └┘        └┘        └───┘  └────
pid                     └──┘└───┘        └┘        └┘                   
st     └────────────────────────────────────────────────────────────────────
436  
src  
typ  
doc  
txt  
par  
pid  
st   
437  theorem repeat_subset_singleton (a : α) (n) : repeat a n ⊆ [a] :=
id                                                └────┘    
src                                                └────┘       
typ                                               └────┘    
438  λ b h, mem_singleton.2 (eq_of_mem_repeat h)
id        └───────────┘   └──────────────┘ 
src         └───────────┘   └──────────────┘
typ       └───────────┘   └──────────────┘ 
439  
440  @[simp] theorem map_const (l : list α) (b : β) : map (function.const α b) l = repeat b l.length :=
id                                  └──┘            └─┘  └────────────┘      └────┘  └─────┘
src                                 └──┘              └─┘  └────────────┘         └────┘    └─────┘
typ                                 └──┘            └─┘  └────────────┘      └────┘  └─────┘
doc    └──┘
441  by induction l; [refl, simp only [*, map]]; split; refl
id                                      └─┘
src     └────────┘   └──┘  └────────────┘└─┘   └───┘  └────
typ     └────────┘  └──┘  └────────────┘└─┘   └───┘  └────
doc     └────────┘    └──┘  └────────────┘      └───┘  └────
txt     └────────┘    └──┘  └────────────┘      └───┘  └────
par     └────────┘    └──┘  └────────────┘      └───┘  └────
pid                            └──┘└───┘                 
st     └─────────────────────────────────────────────────────
442  
src  
typ  
doc  
txt  
par  
pid  
st   
443  theorem eq_of_mem_map_const {b₁ b₂ : β} {l : list α} (h : b₁ ∈ map (function.const α b₂) l) : b₁ = b₂ :=
id                                               └──┘        └┘  └─┘  └────────────┘  └┘      └┘  └┘
src                                               └──┘             └─┘  └────────────┘               
typ                                              └──┘        └┘  └─┘  └────────────┘  └┘      └┘  └┘
444  by rw map_const at h; exact eq_of_mem_repeat h
id         └───────┘             └──────────────┘ 
src     └─┘└───────┘└───┘  └────┘└──────────────┘ 
typ     └─┘└───────┘└───┘  └────┘└──────────────┘
doc     └─┘         └───┘  └────┘                 
txt     └─┘         └───┘  └────┘                 
par     └─┘         └───┘  └────┘                 
pid                └───┘                        
st     └────────────────────────────────────────────
445  
src  
typ  
doc  
txt  
par  
pid  
st   
446  @[simp] theorem map_repeat (f : α → β) (a : α) (n) : map f (repeat a n) = repeat (f a) n :=
id                                                     └─┘   └────┘     └────┘     
src                                                       └─┘    └────┘       └────┘
typ                                                    └─┘   └────┘     └────┘     
doc    └──┘
447  by induction n; [refl, simp only [*, repeat, map]]; split; refl
id                                      └────┘  └─┘
src     └────────┘   └──┘  └────────────┘└────┘└┘└─┘   └───┘  └────
typ     └────────┘  └──┘  └────────────┘└────┘└┘└─┘   └───┘  └────
doc     └────────┘    └──┘  └────────────┘      └┘      └───┘  └────
txt     └────────┘    └──┘  └────────────┘      └┘      └───┘  └────
par     └────────┘    └──┘  └────────────┘      └┘      └───┘  └────
pid                            └──┘└───┘      └┘                 
st     └─────────────────────────────────────────────────────────────
448  
src  
typ  
doc  
txt  
par  
pid  
st   
449  @[simp] theorem tail_repeat (a : α) (n) : tail (repeat a n) = repeat a n.pred :=
id                                            └──┘  └────┘     └────┘  └───┘
src                                            └──┘  └────┘       └────┘    └───┘
typ                                           └──┘  └────┘     └────┘  └───┘
doc    └──┘
450  by cases n; refl
id            
src     └────┘   └────
typ     └────┘  └────
doc     └────┘   └────
txt     └────┘   └────
par     └────┘   └────
pid                 
st     └──────────────
451  
src  
typ  
doc  
txt  
par  
pid  
st   
452  @[simp] theorem join_repeat_nil (n : ℕ) : join (repeat [] n) = @nil α :=
id                                            └──┘  └────┘ └┘     └─┘ 
src                                           └──┘  └────┘ └┘      └─┘
typ                                           └──┘  └────┘ └┘     └─┘ 
doc    └──┘
453  by induction n; [refl, simp only [*, repeat, join, append_nil]]
id                                      └────┘  └──┘  └────────┘
src     └────────┘   └──┘  └────────────┘└────┘└┘└──┘└┘└────────┘
typ     └────────┘  └──┘  └────────────┘└────┘└┘└──┘└┘└────────┘
doc     └────────┘    └──┘  └────────────┘      └┘    └┘          
txt     └────────┘    └──┘  └────────────┘      └┘    └┘          
par     └────────┘    └──┘  └────────────┘      └┘    └┘          
pid                            └──┘└───┘      └┘    └┘          
st     └───────────────────────────────────────────────────────────┘
454  
455  /- bind -/
456  
457  @[simp] theorem bind_eq_bind {α β} (f : α → list β) (l : list α) :
id                                              └──┘        └──┘ 
src                                              └──┘         └──┘
typ                                             └──┘        └──┘ 
doc    └──┘
458    l >>= f = l.bind f := rfl
id      └─┘   └───┘     └─┘
src      └─┘     └───┘      └─┘
typ     └─┘   └───┘     └─┘
459  
460  @[simp] theorem bind_append (f : α → list β) (l₁ l₂ : list α) :
id                                       └──┘            └──┘ 
src                                       └──┘             └──┘
typ                                      └──┘            └──┘ 
doc    └──┘
461    (l₁ ++ l₂).bind f = l₁.bind f ++ l₂.bind f :=
id      └┘ └┘ └┘ └──┘    └┘└───┘  └┘ └┘└───┘ 
src        └┘    └──┘       └───┘   └┘   └───┘
typ     └┘ └┘ └┘ └──┘    └┘└───┘  └┘ └┘└───┘ 
462  append_bind _ _ _
id   └─────────┘
src  └─────────┘
typ  └─────────┘
463  
464  /- concat -/
465  
466  @[simp] theorem concat_nil (a : α) : concat [] a = [a] := rfl
id                                       └────┘ └┘       └─┘
src                                       └────┘ └┘         └─┘
typ                                      └────┘ └┘       └─┘
doc    └──┘                               └────┘
467  
468  @[simp] theorem concat_cons (a b : α) (l : list α) : concat (a :: l) b = a :: concat l b := rfl
id                                             └──┘     └────┘   └┘      └┘ └────┘      └─┘
src                                             └──┘      └────┘    └┘         └┘ └────┘        └─┘
typ                                            └──┘     └────┘   └┘      └┘ └────┘      └─┘
doc    └──┘                                               └────┘                   └────┘
469  
470  @[simp] theorem concat_ne_nil (a : α) (l : list α) : concat l a ≠ [] :=
id                                             └──┘     └────┘    └┘
src                                             └──┘      └────┘      └┘
typ                                            └──┘     └────┘    └┘
doc    └──┘                                               └────┘
471  by induction l; intro h; contradiction
id                
src     └────────┘   └─────┘  └─────────────
typ     └────────┘  └─────┘  └─────────────
doc     └────────┘   └─────┘  └─────────────
txt     └────────┘   └─────┘  └─────────────
par     └────────┘   └─────┘  └─────────────
pid                      └┘               
st     └────────────────────────────────────
472  
src  
typ  
doc  
txt  
par  
pid  
st   
473  @[simp] theorem concat_append (a : α) (l₁ l₂ : list α) : concat l₁ a ++ l₂ = l₁ ++ a :: l₂ :=
id                                                 └──┘     └────┘ └┘  └┘ └┘  └┘ └┘  └┘ └┘
src                                                 └──┘      └────┘      └┘        └┘   └┘
typ                                                └──┘     └────┘ └┘  └┘ └┘  └┘ └┘  └┘ └┘
doc    └──┘                                                   └────┘
474  by induction l₁; simp only [*, cons_append, concat]; split; refl
id                └┘                └─────────┘  └────┘
src     └────────┘    └────────────┘└─────────┘└┘└────┘  └───┘  └────
typ     └────────┘└┘  └────────────┘└─────────┘└┘└────┘  └───┘  └────
doc     └────────┘    └────────────┘           └┘└────┘  └───┘  └────
txt     └────────┘    └────────────┘           └┘        └───┘  └────
par     └────────┘    └────────────┘           └┘        └───┘  └────
pid                      └──┘└───┘           └┘                   
st     └──────────────────────────────────────────────────────────────
475  
src  
typ  
doc  
txt  
par  
pid  
st   
476  @[simp] theorem concat_eq_append (a : α) (l : list α) : concat l a = l ++ [a] :=
id                                                └──┘     └────┘     └┘ 
src                                                └──┘      └────┘        └┘  
typ                                               └──┘     └────┘     └┘ 
doc    └──┘                                                  └────┘
477  by induction l; simp only [*, concat]; split; refl
id                                └────┘
src     └────────┘   └────────────┘└────┘  └───┘  └────
typ     └────────┘  └────────────┘└────┘  └───┘  └────
doc     └────────┘   └────────────┘└────┘  └───┘  └────
txt     └────────┘   └────────────┘        └───┘  └────
par     └────────┘   └────────────┘        └───┘  └────
pid                     └──┘└───┘                   
st     └────────────────────────────────────────────────
478  
src  
typ  
doc  
txt  
par  
pid  
st   
479  @[simp] theorem length_concat (a : α) (l : list α) : length (concat l a) = succ (length l) :=
id                                             └──┘     └────┘  └────┘     └──┘  └────┘ 
src                                             └──┘      └────┘  └────┘       └──┘  └────┘
typ                                            └──┘     └────┘  └────┘     └──┘  └────┘ 
doc    └──┘                                                       └────┘
480  by simp only [concat_eq_append, length_append, length]
id                 └──────────────┘  └───────────┘  └────┘
src     └─────────┘└──────────────┘└┘└───────────┘└┘└────┘└─
typ     └─────────┘└──────────────┘└┘└───────────┘└┘└────┘└─
doc     └─────────┘                └┘             └┘      └─
txt     └─────────┘                └┘             └┘      └─
par     └─────────┘                └┘             └┘      └─
pid         └──┘└┘                └┘             └┘      
st     └────────────────────────────────────────────────────
481  
src  
typ  
doc  
txt  
par  
pid  
st   
482  theorem append_concat (a : α) (l₁ l₂ : list α) : l₁ ++ concat l₂ a = concat (l₁ ++ l₂) a :=
id                                         └──┘     └┘ └┘ └────┘ └┘   └────┘  └┘ └┘ └┘  
src                                         └──┘         └┘ └────┘       └────┘     └┘
typ                                        └──┘     └┘ └┘ └────┘ └┘   └────┘  └┘ └┘ └┘  
doc                                                         └────┘        └────┘
483  by induction l₂ with b l₂ ih; simp only [concat_eq_append, nil_append, cons_append, append_assoc]
id                └┘                          └──────────────┘  └────────┘  └─────────┘  └──────────┘
src     └────────┘  └───────────┘  └─────────┘└──────────────┘└┘└────────┘└┘└─────────┘└┘└──────────┘└─
typ     └────────┘└┘└───────────┘  └─────────┘└──────────────┘└┘└────────┘└┘└─────────┘└┘└──────────┘└─
doc     └────────┘  └───────────┘  └─────────┘                └┘          └┘           └┘            └─
txt     └────────┘  └───────────┘  └─────────┘                └┘          └┘           └┘            └─
par     └────────┘  └───────────┘  └─────────┘                └┘          └┘           └┘            └─
pid                └──────────┘      └──┘└┘                └┘          └┘           └┘            
st     └───────────────────────────────────────────────────────────────────────────────────────────────
484  
src  
typ  
doc  
txt  
par  
pid  
st   
485  /- reverse -/
src  ──────────────
typ  ──────────────
doc  ──────────────
txt  ──────────────
par  ──────────────
pid  ──────────────
st   ──────────────
486  
src  
typ  
doc  
txt  
par  
pid  
st   
487  @[simp] theorem reverse_nil : reverse (@nil α) = [] := rfl
id                                 └─────┘   └─┘    └┘    └─┘
src                                └─────┘   └─┘     └┘    └─┘
typ                                └─────┘   └─┘    └┘    └─┘
doc    └──┘
488  
489  local attribute [simp] reverse_core
id                          └──────────┘
src                         └──────────┘
typ                         └──────────┘
doc                   └──┘
490  
491  @[simp] theorem reverse_cons (a : α) (l : list α) : reverse (a::l) = reverse l ++ [a] :=
id                                            └──┘     └─────┘  └┘   └─────┘  └┘ 
src                                            └──┘      └─────┘   └┘    └─────┘   └┘  
typ                                           └──┘     └─────┘  └┘   └─────┘  └┘ 
doc    └──┘
492  have aux : ∀ l₁ l₂, reverse_core l₁ l₂ ++ [a] = reverse_core l₁ (l₂ ++ [a]),
id                └┘ └┘  └──────────┘ └┘ └┘ └┘   └──────────┘ └┘  └┘ └┘ 
src                      └──────────┘       └┘    └──────────┘        └┘  
typ               └┘ └┘  └──────────┘ └┘ └┘ └┘   └──────────┘ └┘  └┘ └┘ 
493  by intro l₁; induction l₁; intros; [refl, simp only [*, reverse_core, cons_append]],
id                          └┘                              └──────────┘  └─────────┘
src     └──────┘  └────────┘    └────┘  └──┘  └────────────┘└──────────┘└┘└─────────┘
typ     └──────┘  └────────┘└┘  └────┘  └──┘  └────────────┘└──────────┘└┘└─────────┘
doc     └──────┘  └────────┘    └────┘   └──┘  └────────────┘            └┘           
txt     └──────┘  └────────┘    └────┘   └──┘  └────────────┘            └┘           
par     └──────┘  └────────┘    └────┘   └──┘  └────────────┘            └┘           
pid          └─┘                                  └──┘└───┘            └┘           
st     └───────────────────────────────────────────────────────────────────────────────┘
494  (aux l nil).symm
id    └─┘  └─┘ └──┘
src         └─┘ └──┘
typ   └─┘  └─┘ └──┘
495  
496  theorem reverse_core_eq (l₁ l₂ : list α) : reverse_core l₁ l₂ = reverse l₁ ++ l₂ :=
id                                    └──┘     └──────────┘ └┘ └┘  └─────┘ └┘ └┘ └┘
src                                   └──┘      └──────────┘        └─────┘    └┘
typ                                   └──┘     └──────────┘ └┘ └┘  └─────┘ └┘ └┘ └┘
497  by induction l₁ generalizing l₂; [refl, simp only [*, reverse_core, reverse_cons, append_assoc]]; refl
id                └┘                                      └──────────┘  └──────────┘  └──────────┘
src     └────────┘  └──────────────┘  └──┘  └────────────┘└──────────┘└┘└──────────┘└┘└──────────┘   └────
typ     └────────┘└┘└──────────────┘  └──┘  └────────────┘└──────────┘└┘└──────────┘└┘└──────────┘   └────
doc     └────────┘  └──────────────┘   └──┘  └────────────┘            └┘            └┘               └────
txt     └────────┘  └──────────────┘   └──┘  └────────────┘            └┘            └┘               └────
par     └────────┘  └──────────────┘   └──┘  └────────────┘            └┘            └┘               └────
pid                └─────────────┘             └──┘└───┘            └┘            └┘                   
st     └────────────────────────────────────────────────────────────────────────────────────────────────────
498  
src  
typ  
doc  
txt  
par  
pid  
st   
499  theorem reverse_cons' (a : α) (l : list α) : reverse (a::l) = concat (reverse l) a :=
id                                     └──┘     └─────┘  └┘   └────┘  └─────┘   
src                                     └──┘      └─────┘   └┘    └────┘  └─────┘
typ                                    └──┘     └─────┘  └┘   └────┘  └─────┘   
doc                                                                └────┘
500  by simp only [reverse_cons, concat_eq_append]
id                 └──────────┘  └──────────────┘
src     └─────────┘└──────────┘└┘└──────────────┘└─
typ     └─────────┘└──────────┘└┘└──────────────┘└─
doc     └─────────┘            └┘                └─
txt     └─────────┘            └┘                └─
par     └─────────┘            └┘                └─
pid         └──┘└┘            └┘                
st     └───────────────────────────────────────────
501  
src  
typ  
doc  
txt  
par  
pid  
st   
502  @[simp] theorem reverse_singleton (a : α) : reverse [a] = [a] := rfl
id                                              └─────┘       └─┘
src                                              └─────┘         └─┘
typ                                             └─────┘       └─┘
doc    └──┘
503  
504  @[simp] theorem reverse_append (s t : list α) : reverse (s ++ t) = (reverse t) ++ (reverse s) :=
id                                         └──┘     └─────┘   └┘     └─────┘   └┘  └─────┘ 
src                                        └──┘      └─────┘    └┘      └─────┘    └┘  └─────┘
typ                                        └──┘     └─────┘   └┘     └─────┘   └┘  └─────┘ 
doc    └──┘
505  by induction s; [rw [nil_append, reverse_nil, append_nil],
id                      └────────┘  └─────────┘  └────────┘
src     └────────┘   └──┘└────────┘└┘└─────────┘└┘└────────┘
typ     └────────┘  └──┘└────────┘└┘└─────────┘└┘└────────┘
doc     └────────┘    └──┘          └┘           └┘          
txt     └────────┘    └──┘          └┘           └┘          
par     └────────┘    └──┘          └┘           └┘          
pid                    └┘          └┘           └┘          
st     └─────────────────┘└────────┘└───────────┘└──────────┘└─
506  simp only [*, cons_append, reverse_cons, append_assoc]]
id                 └─────────┘  └──────────┘  └──────────┘
src  └────────────┘└─────────┘└┘└──────────┘└┘└──────────┘
typ  └────────────┘└─────────┘└┘└──────────┘└┘└──────────┘
doc  └────────────┘           └┘            └┘            
txt  └────────────┘           └┘            └┘            
par  └────────────┘           └┘            └┘            
pid      └──┘└───┘           └┘            └┘            
st   ──────────────────────────────────────────────────────┘
507  
508  @[simp] theorem reverse_reverse (l : list α) : reverse (reverse l) = l :=
id                                        └──┘     └─────┘  └─────┘    
src                                       └──┘      └─────┘  └─────┘    
typ                                       └──┘     └─────┘  └─────┘    
doc    └──┘
509  by induction l; [refl, simp only [*, reverse_cons, reverse_append]]; refl
id                                      └──────────┘  └────────────┘
src     └────────┘   └──┘  └────────────┘└──────────┘└┘└────────────┘   └────
typ     └────────┘  └──┘  └────────────┘└──────────┘└┘└────────────┘   └────
doc     └────────┘    └──┘  └────────────┘            └┘                 └────
txt     └────────┘    └──┘  └────────────┘            └┘                 └────
par     └────────┘    └──┘  └────────────┘            └┘                 └────
pid                            └──┘└───┘            └┘                     
st     └───────────────────────────────────────────────────────────────────────
510  
src  
typ  
doc  
txt  
par  
pid  
st   
511  theorem reverse_injective : injective (@reverse α) :=
id                               └───────┘   └─────┘ 
src                              └───────┘   └─────┘
typ                              └───────┘   └─────┘ 
512  injective_of_left_inverse reverse_reverse
id   └───────────────────────┘ └─────────────┘
src  └───────────────────────┘ └─────────────┘
typ  └───────────────────────┘ └─────────────┘
513  
514  @[simp] theorem reverse_inj {l₁ l₂ : list α} : reverse l₁ = reverse l₂ ↔ l₁ = l₂ :=
id                                        └──┘     └─────┘ └┘  └─────┘ └┘  └┘  └┘
src                                       └──┘      └─────┘     └─────┘        
typ                                       └──┘     └─────┘ └┘  └─────┘ └┘  └┘  └┘
doc    └──┘
515  reverse_injective.eq_iff
id   └───────────────┘└─────┘
src  └───────────────┘└─────┘
typ  └───────────────┘└─────┘
516  
517  @[simp] theorem reverse_eq_nil {l : list α} : reverse l = [] ↔ l = [] :=
id                                       └──┘     └─────┘   └┘    └┘
src                                      └──┘      └─────┘    └┘     └┘
typ                                      └──┘     └─────┘   └┘    └┘
doc    └──┘
518  @reverse_inj _ l []
id    └─────────┘    └┘
src   └─────────┘     └┘
typ   └─────────┘    └┘
519  
520  theorem concat_eq_reverse_cons (a : α) (l : list α) : concat l a = reverse (a :: reverse l) :=
id                                              └──┘     └────┘    └─────┘   └┘ └─────┘ 
src                                              └──┘      └────┘      └─────┘    └┘ └─────┘
typ                                             └──┘     └────┘    └─────┘   └┘ └─────┘ 
doc                                                        └────┘
521  by simp only [concat_eq_append, reverse_cons, reverse_reverse]
id                 └──────────────┘  └──────────┘  └─────────────┘
src     └─────────┘└──────────────┘└┘└──────────┘└┘└─────────────┘└─
typ     └─────────┘└──────────────┘└┘└──────────┘└┘└─────────────┘└─
doc     └─────────┘                └┘            └┘               └─
txt     └─────────┘                └┘            └┘               └─
par     └─────────┘                └┘            └┘               └─
pid         └──┘└┘                └┘            └┘               
st     └────────────────────────────────────────────────────────────
522  
src  
typ  
doc  
txt  
par  
pid  
st   
523  @[simp] theorem length_reverse (l : list α) : length (reverse l) = length l :=
id                                       └──┘     └────┘  └─────┘    └────┘ 
src                                      └──┘      └────┘  └─────┘     └────┘
typ                                      └──┘     └────┘  └─────┘    └────┘ 
doc    └──┘
524  by induction l; [refl, simp only [*, reverse_cons, length_append, length]]
id                                      └──────────┘  └───────────┘  └────┘
src     └────────┘   └──┘  └────────────┘└──────────┘└┘└───────────┘└┘└────┘
typ     └────────┘  └──┘  └────────────┘└──────────┘└┘└───────────┘└┘└────┘
doc     └────────┘    └──┘  └────────────┘            └┘             └┘      
txt     └────────┘    └──┘  └────────────┘            └┘             └┘      
par     └────────┘    └──┘  └────────────┘            └┘             └┘      
pid                            └──┘└───┘            └┘             └┘      
st     └──────────────────────────────────────────────────────────────────────┘
525  
526  @[simp] theorem map_reverse (f : α → β) (l : list α) : map f (reverse l) = reverse (map f l) :=
id                                              └──┘     └─┘   └─────┘    └─────┘  └─┘  
src                                               └──┘      └─┘    └─────┘     └─────┘  └─┘
typ                                             └──┘     └─┘   └─────┘    └─────┘  └─┘  
doc    └──┘
527  by induction l; [refl, simp only [*, map, reverse_cons, map_append]]
id                                      └─┘  └──────────┘  └────────┘
src     └────────┘   └──┘  └────────────┘└─┘└┘└──────────┘└┘└────────┘
typ     └────────┘  └──┘  └────────────┘└─┘└┘└──────────┘└┘└────────┘
doc     └────────┘    └──┘  └────────────┘   └┘            └┘          
txt     └────────┘    └──┘  └────────────┘   └┘            └┘          
par     └────────┘    └──┘  └────────────┘   └┘            └┘          
pid                            └──┘└───┘   └┘            └┘          
st     └────────────────────────────────────────────────────────────────┘
528  
529  theorem map_reverse_core (f : α → β) (l₁ l₂ : list α) :
id                                               └──┘ 
src                                                └──┘
typ                                              └──┘ 
530    map f (reverse_core l₁ l₂) = reverse_core (map f l₁) (map f l₂) :=
id     └─┘   └──────────┘ └┘ └┘   └──────────┘  └─┘  └┘   └─┘  └┘
src    └─┘    └──────────┘         └──────────┘  └─┘        └─┘
typ    └─┘   └──────────┘ └┘ └┘   └──────────┘  └─┘  └┘   └─┘  └┘
531  by simp only [reverse_core_eq, map_append, map_reverse]
id                 └─────────────┘  └────────┘  └─────────┘
src     └─────────┘└─────────────┘└┘└────────┘└┘└─────────┘└─
typ     └─────────┘└─────────────┘└┘└────────┘└┘└─────────┘└─
doc     └─────────┘               └┘          └┘           └─
txt     └─────────┘               └┘          └┘           └─
par     └─────────┘               └┘          └┘           └─
pid         └──┘└┘               └┘          └┘           
st     └─────────────────────────────────────────────────────
532  
src  
typ  
doc  
txt  
par  
pid  
st   
533  @[simp] theorem mem_reverse {a : α} {l : list α} : a ∈ reverse l ↔ a ∈ l :=
id                                           └──┘       └─────┘     
src                                           └──┘         └─────┘      
typ                                          └──┘       └─────┘     
doc    └──┘
534  by induction l; [refl, simp only [*, reverse_cons, mem_append, mem_singleton, mem_cons_iff, not_mem_nil, false_or, or_false, or_comm]]
id                                      └──────────┘  └────────┘  └───────────┘  └──────────┘  └─────────┘  └──────┘  └──────┘  └─────┘
src     └────────┘   └──┘  └────────────┘└──────────┘└┘└────────┘└┘└───────────┘└┘└──────────┘└┘└─────────┘└┘└──────┘└┘└──────┘└┘└─────┘
typ     └────────┘  └──┘  └────────────┘└──────────┘└┘└────────┘└┘└───────────┘└┘└──────────┘└┘└─────────┘└┘└──────┘└┘└──────┘└┘└─────┘
doc     └────────┘    └──┘  └────────────┘            └┘          └┘             └┘            └┘           └┘        └┘        └┘       
txt     └────────┘    └──┘  └────────────┘            └┘          └┘             └┘            └┘           └┘        └┘        └┘       
par     └────────┘    └──┘  └────────────┘            └┘          └┘             └┘            └┘           └┘        └┘        └┘       
pid                            └──┘└───┘            └┘          └┘             └┘            └┘           └┘        └┘        └┘       
st     └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
535  
536  @[simp] theorem reverse_repeat (a : α) (n) : reverse (repeat a n) = repeat a n :=
id                                               └─────┘  └────┘     └────┘  
src                                               └─────┘  └────┘       └────┘
typ                                              └─────┘  └────┘     └────┘  
doc    └──┘
537  eq_repeat.2 ⟨by simp only [length_reverse, length_repeat], λ b h, eq_of_mem_repeat (mem_reverse.1 h)⟩
id   └───────┘                 └────────────┘  └───────────┘        └──────────────┘  └─────────┘  
src  └───────┘      └─────────┘└────────────┘└┘└───────────┘         └──────────────┘  └─────────┘
typ  └───────┘      └─────────┘└────────────┘└┘└───────────┘       └──────────────┘  └─────────┘  
doc                  └─────────┘              └┘             
txt                  └─────────┘              └┘             
par                  └─────────┘              └┘             
pid                      └──┘└┘              └┘             
st                  └────────────────────────────────────────┘
538  
539  @[elab_as_eliminator] def reverse_rec_on {C : list α → Sort*}
id                                                 └──┘ 
src                                                └──┘
typ                                                └──┘ 
doc    └────────────────┘
540    (l : list α) (H0 : C [])
id          └──┘          └┘
src         └──┘            └┘
typ         └──┘          └┘
541    (H1 : ∀ (l : list α) (a : α), C l → C (l ++ [a])) : C l :=
id                  └──┘                  └┘       
src                 └──┘                        └┘  
typ                 └──┘                  └┘       
542  begin
st   └─────
543    rw ← reverse_reverse l,
id          └─────────────┘ 
src    └───┘└─────────────┘
typ    └───┘└─────────────┘
doc    └───┘               
txt    └───┘               
par    └───┘               
pid      └─┘               
st   ───────────────────────┘└─
544    induction reverse l,
id               └─────┘ 
src    └────────┘└─────┘
typ    └────────┘└─────┘
doc    └────────┘       
txt    └────────┘       
par    └────────┘       
pid                    
st   ────────────────────┘└─
545    { exact H0 },
id             └┘
src      └────┘  
typ      └────┘└┘
doc      └────┘  
txt      └────┘  
par      └────┘  
pid             
st   ───┘└───────┘└┘
546    { rw reverse_cons, exact H1 _ _ ih }
id          └──────────┘        └┘     └┘
src      └─┘└──────────┘  └────┘  └───┘  
typ      └─┘└──────────┘  └────┘└┘└───┘└┘
doc      └─┘              └────┘  └───┘  
txt      └─┘              └────┘  └───┘  
par      └─┘              └────┘  └───┘  
pid                             └───┘  
st   ──────────────────┘└────────────────┘└─
547  end
st   ──┘
548  
549  /- last -/
550  
551  @[simp] theorem last_cons {a : α} {l : list α} : ∀ (h₁ : a :: l ≠ nil) (h₂ : l ≠ nil), last (a :: l) h₁ = last l h₂ :=
id                                         └──┘              └┘   └─┘          └─┘   └──┘   └┘   └┘  └──┘  └┘
src                                         └──┘                └┘    └─┘           └─┘   └──┘    └┘        └──┘
typ                                        └──┘              └┘   └─┘          └─┘   └──┘   └┘   └┘  └──┘  └┘
doc    └──┘
552  by {induction l; intros, contradiction, reflexivity}
id                 
src      └────────┘   └────┘  └───────────┘  └─────────┘
typ      └────────┘  └────┘  └───────────┘  └─────────┘
doc      └────────┘   └────┘  └───────────┘  └─────────┘
txt      └────────┘   └────┘  └───────────┘  └─────────┘
par      └────────┘   └────┘  └───────────┘  └─────────┘
pid               
st     └───────────────────┘└─────────────┘└───────────┘└┘
553  
554  @[simp] theorem last_append {a : α} (l : list α) (h : l ++ [a] ≠ []) : last (l ++ [a]) h = a :=
id                                           └──┘         └┘   └┘    └──┘   └┘     
src                                           └──┘           └┘    └┘    └──┘    └┘      
typ                                          └──┘         └┘   └┘    └──┘   └┘     
doc    └──┘
555  by induction l; [refl, simp only [cons_append, last_cons _ (λ H, cons_ne_nil _ _ (append_eq_nil.1 H).2), *]]
id                                   └─────────┘  └───────┘         └─────────┘      └───────────┘
src     └────────┘   └──┘  └─────────┘└─────────┘└┘└───────┘└─┘  └──┘└─────────┘└───┘ └───────────┘└─┘ └──────┘
typ     └────────┘  └──┘  └─────────┘└─────────┘└┘└───────┘└─┘  └──┘└─────────┘└───┘ └───────────┘└─┘ └──────┘
doc     └────────┘    └──┘  └─────────┘           └┘         └─┘  └──┘           └───┘              └─┘ └──────┘
txt     └────────┘    └──┘  └─────────┘           └┘         └─┘  └──┘           └───┘              └─┘ └──────┘
par     └────────┘    └──┘  └─────────┘           └┘         └─┘  └──┘           └───┘              └─┘ └──────┘
pid                            └──┘└┘           └┘         └─┘  └──┘           └───┘              └─┘ └──────┘
st     └────────────────────────────────────────────────────────────────────────────────────────────────────────┘
556  
557  theorem last_concat {a : α} (l : list α) (h : concat l a ≠ []) : last (concat l a) h = a :=
id                                   └──┘        └────┘    └┘    └──┘  └────┘      
src                                   └──┘         └────┘      └┘    └──┘  └────┘        
typ                                  └──┘        └────┘    └┘    └──┘  └────┘      
doc                                                └────┘                   └────┘
558  by simp only [concat_eq_append, last_append]
id                 └──────────────┘  └─────────┘
src     └─────────┘└──────────────┘└┘└─────────┘└─
typ     └─────────┘└──────────────┘└┘└─────────┘└─
doc     └─────────┘                └┘           └─
txt     └─────────┘                └┘           └─
par     └─────────┘                └┘           └─
pid         └──┘└┘                └┘           
st     └──────────────────────────────────────────
559  
src  
typ  
doc  
txt  
par  
pid  
st   
560  @[simp] theorem last_singleton (a : α) (h : [a] ≠ []) : last [a] h = a := rfl
id                                                └┘    └──┘        └─┘
src                                                 └┘    └──┘           └─┘
typ                                               └┘    └──┘        └─┘
doc    └──┘
561  
562  @[simp] theorem last_cons_cons (a₁ a₂ : α) (l : list α) (h : a₁::a₂::l ≠ []) :
id                                                  └──┘        └┘└┘└┘└┘  └┘
src                                                  └──┘           └┘  └┘   └┘
typ                                                 └──┘        └┘└┘└┘└┘  └┘
doc    └──┘
563    last (a₁::a₂::l) h = last (a₂::l) (cons_ne_nil a₂ l) := rfl
id     └──┘  └┘└┘└┘└┘    └──┘  └┘└┘   └─────────┘ └┘      └─┘
src    └──┘    └┘  └┘      └──┘    └┘    └─────────┘          └─┘
typ    └──┘  └┘└┘└┘└┘    └──┘  └┘└┘   └─────────┘ └┘      └─┘
564  
565  theorem last_congr {l₁ l₂ : list α} (h₁ : l₁ ≠ []) (h₂ : l₂ ≠ []) (h₃ : l₁ = l₂) :
id                               └──┘         └┘  └┘        └┘  └┘        └┘  └┘
src                              └──┘              └┘            └┘           
typ                              └──┘         └┘  └┘        └┘  └┘        └┘  └┘
566    last l₁ h₁ = last l₂ h₂ :=
id     └──┘ └┘ └┘  └──┘ └┘ └┘
src    └──┘        └──┘
typ    └──┘ └┘ └┘  └──┘ └┘ └┘
567  by subst l₁
id            └┘
src     └────┘  
typ     └────┘└┘
doc     └────┘  
txt     └────┘  
par     └────┘  
pid            
st     └─────────
568  
src  
typ  
doc  
txt  
par  
pid  
st   
569  /- head(') and tail -/
src  ───────────────────────
typ  ───────────────────────
doc  ───────────────────────
txt  ───────────────────────
par  ───────────────────────
pid  ───────────────────────
st   ───────────────────────
570  
src  
typ  
doc  
txt  
par  
pid  
st   
571  theorem head_eq_head' [inhabited α] (l : list α) : head l = (head' l).iget :=
id                          └───────┘        └──┘     └──┘    └───┘  └──┘
src                         └───────┘         └──┘      └──┘     └───┘   └──┘
typ                         └───────┘        └──┘     └──┘    └───┘  └──┘
doc                                                                       └──┘
572  by cases l; refl
id            
src     └────┘   └────
typ     └────┘  └────
doc     └────┘   └────
txt     └────┘   └────
par     └────┘   └────
pid                 
st     └──────────────
573  
src  
typ  
doc  
txt  
par  
pid  
st   
574  @[simp] theorem head_cons [inhabited α] (a : α) (l : list α) : head (a::l) = a := rfl
id                              └───────┘               └──┘     └──┘  └┘       └─┘
src                             └───────┘                 └──┘      └──┘   └┘         └─┘
typ                             └───────┘               └──┘     └──┘  └┘       └─┘
doc    └──┘
575  
576  @[simp] theorem tail_nil : tail (@nil α) = [] := rfl
id                              └──┘   └─┘    └┘    └─┘
src                             └──┘   └─┘     └┘    └─┘
typ                             └──┘   └─┘    └┘    └─┘
doc    └──┘
577  
578  @[simp] theorem tail_cons (a : α) (l : list α) : tail (a::l) = l := rfl
id                                         └──┘     └──┘  └┘       └─┘
src                                         └──┘      └──┘   └┘         └─┘
typ                                        └──┘     └──┘  └┘       └─┘
doc    └──┘
579  
580  @[simp] theorem head_append [inhabited α] (t : list α) {s : list α} (h : s ≠ []) : head (s ++ t) = head s :=
id                                └───────┘        └──┘        └──┘          └┘    └──┘   └┘    └──┘ 
src                               └───────┘         └──┘         └──┘            └┘    └──┘    └┘     └──┘
typ                               └───────┘        └──┘        └──┘          └┘    └──┘   └┘    └──┘ 
doc    └──┘
581  by {induction s, contradiction, refl}
id                 
src      └────────┘   └───────────┘  └──┘
typ      └────────┘  └───────────┘  └──┘
doc      └────────┘   └───────────┘  └──┘
txt      └────────┘   └───────────┘  └──┘
par      └────────┘   └───────────┘  └──┘
pid               
st     └───────────┘└─────────────┘└────┘└┘
582  
583  theorem cons_head_tail [inhabited α] {l : list α} (h : l ≠ []) : (head l)::(tail l) = l :=
id                           └───────┘        └──┘          └┘     └──┘  └┘ └──┘    
src                          └───────┘         └──┘            └┘     └──┘   └┘ └──┘    
typ                          └───────┘        └──┘          └┘     └──┘  └┘ └──┘    
584  by {induction l, contradiction, refl}
id                 
src      └────────┘   └───────────┘  └──┘
typ      └────────┘  └───────────┘  └──┘
doc      └────────┘   └───────────┘  └──┘
txt      └────────┘   └───────────┘  └──┘
par      └────────┘   └───────────┘  └──┘
pid               
st     └───────────┘└─────────────┘└────┘└┘
585  
586  /- sublists -/
587  
588  @[simp] theorem nil_sublist : Π (l : list α), [] <+ l
id                                       └──┘    └┘ └┘ 
src                                       └──┘     └┘ └┘
typ                                      └──┘    └┘ └┘ 
doc    └──┘
589  | []       := sublist.slnil
id     └┘          └───────────┘
src    └┘          └───────────┘
typ    └┘          └───────────┘
590  | (a :: l) := sublist.cons _ _ a (nil_sublist l)
id       └┘      └──────────┘        └─────────┘
src       └┘       └──────────┘
typ      └┘      └──────────┘        └─────────┘
591  
592  @[refl, simp] theorem sublist.refl : Π (l : list α), l <+ l
id                                              └──┘     └┘ 
src    └──┘                                      └──┘       └┘
typ                                             └──┘     └┘ 
doc    └──┘  └──┘
593  | []       := sublist.slnil
id     └┘          └───────────┘
src    └┘          └───────────┘
typ    └┘          └───────────┘
594  | (a :: l) := sublist.cons2 _ _ a (sublist.refl l)
id       └┘      └───────────┘        └──────────┘
src       └┘       └───────────┘
typ      └┘      └───────────┘        └──────────┘
595  
596  @[trans] theorem sublist.trans {l₁ l₂ l₃ : list α} (h₁ : l₁ <+ l₂) (h₂ : l₂ <+ l₃) : l₁ <+ l₃ :=
id                                              └──┘         └┘ └┘ └┘        └┘ └┘ └┘    └┘ └┘ └┘
src    └───┘                                    └──┘             └┘              └┘          └┘
typ                                             └──┘         └┘ └┘ └┘        └┘ └┘ └┘    └┘ └┘ └┘
doc    └───┘
597  sublist.rec_on h₂ (λ_ s, s)
id   └────────────┘ └┘      
src  └────────────┘
typ  └────────────┘ └┘      
598    (λl₂ l₃ a h₂ IH l₁ h₁, sublist.cons _ _ _ (IH l₁ h₁))
id       └┘ └┘  └┘ └┘ └┘ └┘  └──────────┘        └┘ └┘ └┘
src                           └──────────┘
typ      └┘ └┘  └┘ └┘ └┘ └┘  └──────────┘        └┘ └┘ └┘
599    (λl₂ l₃ a h₂ IH l₁ h₁, @sublist.cases_on _ (λl₁ l₂', l₂' = a :: l₂ → l₁ <+ a :: l₃) _ _ h₁
id       └┘ └┘  └┘ └┘ └┘ └┘   └──────────────┘     └┘ └─┘  └─┘   └┘ └┘   └┘ └┘  └┘ └┘      └┘
src                            └──────────────┘                    └┘         └┘   └┘
typ      └┘ └┘  └┘ └┘ └┘ └┘   └──────────────┘     └┘ └─┘  └─┘   └┘ └┘   └┘ └┘  └┘ └┘      └┘
600      (λ_, nil_sublist _)
id           └─────────┘
src           └─────────┘
typ          └─────────┘
601      (λl₁ l₂' a' h₁' e, match a', l₂', e, h₁' with ._, ._, rfl, h₁ := sublist.cons _ _ _ (IH _ h₁) end)
id         └┘ └─┘ └┘ └─┘         └┘  └─┘    └─┘              └─┘  └┘    └──────────┘        └┘
src                                                            └─┘        └──────────┘
typ        └┘ └─┘ └┘ └─┘         └┘  └─┘    └─┘              └─┘  └┘    └──────────┘        └┘
602      (λl₁ l₂' a' h₁' e, match a', l₂', e, h₁' with ._, ._, rfl, h₁ := sublist.cons2 _ _ _ (IH _ h₁) end) rfl)
id         └┘ └─┘ └┘ └─┘         └┘  └─┘    └─┘              └─┘  └┘    └───────────┘        └┘            └─┘
src                                                            └─┘        └───────────┘                      └─┘
typ        └┘ └─┘ └┘ └─┘         └┘  └─┘    └─┘              └─┘  └┘    └───────────┘        └┘            └─┘
603    l₁ h₁
id     └┘ └┘
typ    └┘ └┘
604  
605  @[simp] theorem sublist_cons (a : α) (l : list α) : l <+ a::l :=
id                                            └──┘      └┘ └┘
src                                            └──┘        └┘  └┘
typ                                           └──┘      └┘ └┘
doc    └──┘
606  sublist.cons _ _ _ (sublist.refl l)
id   └──────────┘        └──────────┘ 
src  └──────────┘        └──────────┘
typ  └──────────┘        └──────────┘ 
607  
608  theorem sublist_of_cons_sublist {a : α} {l₁ l₂ : list α} : a::l₁ <+ l₂ → l₁ <+ l₂ :=
id                                                   └──┘     └┘└┘ └┘ └┘   └┘ └┘ └┘
src                                                   └──┘       └┘   └┘         └┘
typ                                                  └──┘     └┘└┘ └┘ └┘   └┘ └┘ └┘
609  sublist.trans (sublist_cons a l₁)
id   └───────────┘  └──────────┘  └┘
src  └───────────┘  └──────────┘
typ  └───────────┘  └──────────┘  └┘
610  
611  theorem cons_sublist_cons {l₁ l₂ : list α} (a : α) (s : l₁ <+ l₂) : a::l₁ <+ a::l₂ :=
id                                      └──┘               └┘ └┘ └┘    └┘└┘ └┘ └┘└┘
src                                     └──┘                    └┘        └┘   └┘  └┘
typ                                     └──┘               └┘ └┘ └┘    └┘└┘ └┘ └┘└┘
612  sublist.cons2 _ _ _ s
id   └───────────┘       
src  └───────────┘
typ  └───────────┘       
613  
614  @[simp] theorem sublist_append_left : Π (l₁ l₂ : list α), l₁ <+ l₁++l₂
id                                                   └──┘    └┘ └┘ └┘└┘└┘
src                                                   └──┘        └┘   └┘
typ                                                  └──┘    └┘ └┘ └┘└┘└┘
doc    └──┘
615  | []      l₂ := nil_sublist _
id     └┘            └─────────┘
src    └┘            └─────────┘
typ    └┘            └─────────┘
616  | (a::l₁) l₂ := cons_sublist_cons _ (sublist_append_left l₁ l₂)
id       └┘└┘  └┘    └───────────────┘    └─────────────────┘
src      └┘          └───────────────┘
typ      └┘└┘  └┘    └───────────────┘    └─────────────────┘
617  
618  @[simp] theorem sublist_append_right : Π (l₁ l₂ : list α), l₂ <+ l₁++l₂
id                                                    └──┘    └┘ └┘ └┘└┘└┘
src                                                    └──┘        └┘   └┘
typ                                                   └──┘    └┘ └┘ └┘└┘└┘
doc    └──┘
619  | []      l₂ := sublist.refl _
id     └┘            └──────────┘
src    └┘            └──────────┘
typ    └┘            └──────────┘
620  | (a::l₁) l₂ := sublist.cons _ _ _ (sublist_append_right l₁ l₂)
id       └┘└┘  └┘    └──────────┘        └──────────────────┘
src      └┘          └──────────┘
typ      └┘└┘  └┘    └──────────┘        └──────────────────┘
621  
622  theorem sublist_cons_of_sublist (a : α) {l₁ l₂ : list α} : l₁ <+ l₂ → l₁ <+ a::l₂ :=
id                                                   └──┘     └┘ └┘ └┘   └┘ └┘ └┘└┘
src                                                   └──┘         └┘         └┘  └┘
typ                                                  └──┘     └┘ └┘ └┘   └┘ └┘ └┘└┘
623  sublist.cons _ _ _
id   └──────────┘
src  └──────────┘
typ  └──────────┘
624  
625  theorem sublist_append_of_sublist_left {l l₁ l₂ : list α} (s : l <+ l₁) : l <+ l₁++l₂ :=
id                                                     └──┘         └┘ └┘     └┘ └┘└┘└┘
src                                                    └──┘           └┘         └┘   └┘
typ                                                    └──┘         └┘ └┘     └┘ └┘└┘└┘
626  s.trans $ sublist_append_left _ _
id   └────┘   └─────────────────┘
src   └────┘   └─────────────────┘
typ  └────┘   └─────────────────┘
627  
628  theorem sublist_append_of_sublist_right {l l₁ l₂ : list α} (s : l <+ l₂) : l <+ l₁++l₂ :=
id                                                      └──┘         └┘ └┘     └┘ └┘└┘└┘
src                                                     └──┘           └┘         └┘   └┘
typ                                                     └──┘         └┘ └┘     └┘ └┘└┘└┘
629  s.trans $ sublist_append_right _ _
id   └────┘   └──────────────────┘
src   └────┘   └──────────────────┘
typ  └────┘   └──────────────────┘
630  
631  theorem sublist_of_cons_sublist_cons {l₁ l₂ : list α} : ∀ {a : α}, a::l₁ <+ a::l₂ → l₁ <+ l₂
id                                                 └──┘              └┘└┘ └┘ └┘└┘   └┘ └┘ └┘
src                                                └──┘                  └┘   └┘  └┘        └┘
typ                                                └──┘              └┘└┘ └┘ └┘└┘   └┘ └┘ └┘
632  | ._ (sublist.cons  ._ ._ a s) := sublist_of_cons_sublist s
id         └──────────┘               └─────────────────────┘
src        └──────────┘                └─────────────────────┘
typ        └──────────┘               └─────────────────────┘
633  | ._ (sublist.cons2 ._ ._ a s) := s
id         └───────────┘         
src        └───────────┘
typ        └───────────┘         
634  
635  theorem cons_sublist_cons_iff {l₁ l₂ : list α} {a : α} : a::l₁ <+ a::l₂ ↔ l₁ <+ l₂ :=
id                                          └──┘            └┘└┘ └┘ └┘└┘  └┘ └┘ └┘
src                                         └──┘               └┘   └┘  └┘       └┘
typ                                         └──┘            └┘└┘ └┘ └┘└┘  └┘ └┘ └┘
636  ⟨sublist_of_cons_sublist_cons, cons_sublist_cons _⟩
id    └──────────────────────────┘  └───────────────┘
src   └──────────────────────────┘  └───────────────┘
typ   └──────────────────────────┘  └───────────────┘
637  
638  @[simp] theorem append_sublist_append_left {l₁ l₂ : list α} : ∀ l, l++l₁ <+ l++l₂ ↔ l₁ <+ l₂
id                                                       └──┘         └┘└┘ └┘ └┘└┘  └┘ └┘ └┘
src                                                      └──┘            └┘   └┘  └┘       └┘
typ                                                      └──┘         └┘└┘ └┘ └┘└┘  └┘ └┘ └┘
doc    └──┘
639  | []     := iff.rfl
id     └┘        └─────┘
src    └┘        └─────┘
typ    └┘        └─────┘
640  | (a::l) := cons_sublist_cons_iff.trans (append_sublist_append_left l)
id       └┘     └───────────────────┘└────┘  └────────────────────────┘
src      └┘      └───────────────────┘└────┘
typ      └┘     └───────────────────┘└────┘  └────────────────────────┘
641  
642  theorem append_sublist_append_of_sublist_right {l₁ l₂ : list α} (h : l₁ <+ l₂) (l) : l₁++l <+ l₂++l :=
id                                                           └──┘        └┘ └┘ └┘        └┘└┘ └┘ └┘└┘
src                                                          └──┘            └┘             └┘  └┘   └┘
typ                                                          └──┘        └┘ └┘ └┘        └┘└┘ └┘ └┘└┘
643  begin
st   └─────
644    induction h with _ _ a _ ih _ _ a _ ih,
id               
src    └────────┘ └─────────────────────────┘
typ    └────────┘└─────────────────────────┘
doc    └────────┘ └─────────────────────────┘
txt    └────────┘ └─────────────────────────┘
par    └────────┘ └─────────────────────────┘
pid              └────────────────────────┘
st   ───────────────────────────────────────┘└─
645    { refl },
src      └───┘
typ      └───┘
doc      └───┘
txt      └───┘
par      └───┘
pid          
st   ───┘└───┘└┘
646    { apply sublist_cons_of_sublist a ih },
id             └─────────────────────┘  └┘
src      └────┘└─────────────────────┘   
typ      └────┘└─────────────────────┘└┘
doc      └────┘                          
txt      └────┘                          
par      └────┘                          
pid                                     
st   ───┘└─────────────────────────────────┘└┘
647    { apply cons_sublist_cons a ih }
id             └───────────────┘  └┘
src      └────┘└───────────────┘   
typ      └────┘└───────────────┘└┘
doc      └────┘                    
txt      └────┘                    
par      └────┘                    
pid                               
st   ────────────────────────────────┘└─
648  end
st   ──┘
649  
650  theorem sublist_or_mem_of_sublist {l l₁ l₂ : list α} {a : α} (h : l <+ l₁ ++ a::l₂) : l <+ l₁ ++ l₂ ∨ a ∈ l :=
id                                                └──┘                └┘ └┘ └┘ └┘└┘     └┘ └┘ └┘ └┘    
src                                               └──┘                   └┘    └┘  └┘        └┘    └┘       
typ                                               └──┘                └┘ └┘ └┘ └┘└┘     └┘ └┘ └┘ └┘    
651  begin
st   └─────
652    induction l₁ with b l₁ IH generalizing l,
id               └┘
src    └────────┘  └──────────────────────────┘
typ    └────────┘└┘└──────────────────────────┘
doc    └────────┘  └──────────────────────────┘
txt    └────────┘  └──────────────────────────┘
par    └────────┘  └──────────────────────────┘
pid               └──────────┘└─────────────┘
st   ─────────────────────────────────────────┘└─
653    { cases h, { left, exact ‹l <+ l₂› }, { right, apply mem_cons_self } },
id                              └┘ └┘                   └───────────┘
src      └────┘     └──┘  └────┘ └┘       └───┘  └────┘└───────────┘
typ      └────┘    └──┘  └────┘└┘└┘     └───┘  └────┘└───────────┘
doc      └────┘     └──┘  └────┘          └───┘  └────┘             
txt      └────┘     └──┘  └────┘            └───┘  └────┘             
par      └────┘     └──┘  └────┘            └───┘  └────┘             
pid                                                                
st   ───┘└─────┘└──┘└──┘└────────────────┘└┘└──────┘└────────────────────┘└──┘
654    { cases h with _ _ _ h _ _ _ h,
id             
src      └────┘ └───────────────────┘
typ      └────┘└───────────────────┘
doc      └────┘ └───────────────────┘
txt      └────┘ └───────────────────┘
par      └────┘ └───────────────────┘
pid            └───────────────────┘
st   ───────────────────────────────┘└─
655      { exact or.imp_left (sublist_cons_of_sublist _) (IH h) },
id               └─────────┘  └─────────────────────┘     └┘ 
src        └────┘└─────────┘ └─────────────────────┘└──┘    └┘
typ        └────┘└─────────┘ └─────────────────────┘└──┘ └┘└┘
doc        └────┘                                   └──┘    └┘
txt        └────┘                                   └──┘    └┘
par        └────┘                                   └──┘    └┘
pid                                                └──┘    
st   ─────┘└───────────────────────────────────────────────────┘└┘
656      { exact (IH h).imp (cons_sublist_cons _) (mem_cons_of_mem _) } }
id                └┘        └───────────────┘     └─────────────┘
src        └────┘    └────┘ └───────────────┘└──┘ └─────────────┘└──┘
typ        └────┘ └┘└────┘ └───────────────┘└──┘ └─────────────┘└──┘
doc        └────┘    └────┘                  └──┘                └──┘
txt        └────┘    └────┘                  └──┘                └──┘
par        └────┘    └────┘                  └──┘                └──┘
pid                 └────┘                  └──┘                └─┘
st   ────────────────────────────────────────────────────────────────┘└───
657  end
st   ──┘
658  
659  theorem reverse_sublist {l₁ l₂ : list α} (h : l₁ <+ l₂) : l₁.reverse <+ l₂.reverse :=
id                                    └──┘        └┘ └┘ └┘    └┘└──────┘ └┘ └┘└──────┘
src                                   └──┘            └┘         └──────┘ └┘   └──────┘
typ                                   └──┘        └┘ └┘ └┘    └┘└──────┘ └┘ └┘└──────┘
660  begin
st   └─────
661    induction h with _ _ _ _ ih _ _ a _ ih, {refl},
id               
src    └────────┘ └─────────────────────────┘   └──┘
typ    └────────┘└─────────────────────────┘   └──┘
doc    └────────┘ └─────────────────────────┘   └──┘
txt    └────────┘ └─────────────────────────┘   └──┘
par    └────────┘ └─────────────────────────┘   └──┘
pid              └────────────────────────┘
st   ───────────────────────────────────────┘└─────┘└┘
662    { rw reverse_cons, exact sublist_append_of_sublist_left ih },
id          └──────────┘        └────────────────────────────┘ └┘
src      └─┘└──────────┘  └────┘└────────────────────────────┘  
typ      └─┘└──────────┘  └────┘└────────────────────────────┘└┘
doc      └─┘              └────┘                                
txt      └─┘              └────┘                                
par      └─┘              └────┘                                
pid                                                           
st   ───┘└─────────────┘└────────────────────────────────────────┘└┘
663    { rw [reverse_cons, reverse_cons], exact append_sublist_append_of_sublist_right ih [a] }
id           └──────────┘  └──────────┘         └────────────────────────────────────┘ └┘  
src      └──┘└──────────┘└┘└──────────┘  └────┘└────────────────────────────────────┘     
typ      └──┘└──────────┘└┘└──────────┘  └────┘└────────────────────────────────────┘└┘  
doc      └──┘            └┘              └────┘                                           
txt      └──┘            └┘              └────┘                                           
par      └──┘            └┘              └────┘                                           
pid        └┘            └┘                                                              
st   ───────────────────┘└────────────┘└────────────────────────────────────────────────────┘└─
664  end
st   ──┘
665  
666  @[simp] theorem reverse_sublist_iff {l₁ l₂ : list α} : l₁.reverse <+ l₂.reverse ↔ l₁ <+ l₂ :=
id                                                └──┘     └┘└──────┘ └┘ └┘└──────┘  └┘ └┘ └┘
src                                               └──┘        └──────┘ └┘   └──────┘     └┘
typ                                               └──┘     └┘└──────┘ └┘ └┘└──────┘  └┘ └┘ └┘
doc    └──┘
667  ⟨λ h, by have := reverse_sublist h; simp only [reverse_reverse] at this; assumption, reverse_sublist⟩
id                   └─────────────┘              └─────────────┘                       └─────────────┘
src           └──────┘└─────────────┘   └─────────┘└─────────────┘└───────┘  └────────┘  └─────────────┘
typ          └──────┘└─────────────┘  └─────────┘└─────────────┘└───────┘  └────────┘  └─────────────┘
doc           └──────┘                  └─────────┘               └───────┘  └────────┘
txt           └──────┘                  └─────────┘               └───────┘  └────────┘
par           └──────┘                  └─────────┘               └───────┘  └────────┘
pid           └───┘└─┘                      └──┘└┘               └─────┘
st           └─────────────────────────────────────────────────────────────────────────┘
668  
669  @[simp] theorem append_sublist_append_right {l₁ l₂ : list α} (l) : l₁++l <+ l₂++l ↔ l₁ <+ l₂ :=
id                                                        └──┘         └┘└┘ └┘ └┘└┘  └┘ └┘ └┘
src                                                       └──┘            └┘  └┘   └┘      └┘
typ                                                       └──┘         └┘└┘ └┘ └┘└┘  └┘ └┘ └┘
doc    └──┘
670  ⟨λ h, by have := reverse_sublist h; simp only [reverse_append, append_sublist_append_left, reverse_sublist_iff] at this; assumption,
id                   └─────────────┘              └────────────┘  └────────────────────────┘  └─────────────────┘
src           └──────┘└─────────────┘   └─────────┘└────────────┘└┘└────────────────────────┘└┘└─────────────────┘└───────┘  └────────┘
typ          └──────┘└─────────────┘  └─────────┘└────────────┘└┘└────────────────────────┘└┘└─────────────────┘└───────┘  └────────┘
doc           └──────┘                  └─────────┘              └┘                          └┘                   └───────┘  └────────┘
txt           └──────┘                  └─────────┘              └┘                          └┘                   └───────┘  └────────┘
par           └──────┘                  └─────────┘              └┘                          └┘                   └───────┘  └────────┘
pid           └───┘└─┘                      └──┘└┘              └┘                          └┘                   └─────┘
st           └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
671   λ h, append_sublist_append_of_sublist_right h l⟩
id        └────────────────────────────────────┘  
src        └────────────────────────────────────┘
typ       └────────────────────────────────────┘  
672  
673  theorem append_sublist_append {l₁ l₂ r₁ r₂ : list α}
id                                                └──┘ 
src                                               └──┘
typ                                               └──┘ 
674    (hl : l₁ <+ l₂) (hr : r₁ <+ r₂) : l₁ ++ r₁ <+ l₂ ++ r₂ :=
id           └┘ └┘ └┘        └┘ └┘ └┘    └┘ └┘ └┘ └┘ └┘ └┘ └┘
src             └┘              └┘          └┘    └┘    └┘
typ          └┘ └┘ └┘        └┘ └┘ └┘    └┘ └┘ └┘ └┘ └┘ └┘ └┘
675  (append_sublist_append_of_sublist_right hl _).trans
id    └────────────────────────────────────┘ └┘   └───┘
src   └────────────────────────────────────┘      └───┘
typ   └────────────────────────────────────┘ └┘   └───┘
676    ((append_sublist_append_left _).2 hr)
id       └────────────────────────┘     └┘
src      └────────────────────────┘   
typ      └────────────────────────┘     └┘
677  
678  theorem subset_of_sublist : Π {l₁ l₂ : list α}, l₁ <+ l₂ → l₁ ⊆ l₂
id                                         └──┘    └┘ └┘ └┘   └┘  └┘
src                                         └──┘        └┘         
typ                                        └──┘    └┘ └┘ └┘   └┘  └┘
679  | ._ ._ sublist.slnil             b h := h
id           └───────────┘               
src          └───────────┘
typ          └───────────┘               
680  | ._ ._ (sublist.cons  l₁ l₂ a s) b h := mem_cons_of_mem _ (subset_of_sublist s h)
id            └──────────┘                  └─────────────┘    └───────────────┘
src           └──────────┘                    └─────────────┘
typ           └──────────┘                  └─────────────┘    └───────────────┘
681  | ._ ._ (sublist.cons2 l₁ l₂ a s) b h :=
id            └───────────┘             
src           └───────────┘
typ           └───────────┘             
682    match eq_or_mem_of_mem_cons h with
id           └───────────────────┘
src          └───────────────────┘
typ          └───────────────────┘
683    | or.inl h := h ▸ mem_cons_self _ _
id       └────┘        └───────────┘
src      └────┘         └───────────┘
typ      └────┘        └───────────┘
684    | or.inr h := mem_cons_of_mem _ (subset_of_sublist s h)
id       └────┘     └─────────────┘    └───────────────┘
src      └────┘      └─────────────┘
typ      └────┘     └─────────────┘    └───────────────┘
685    end
686  
687  theorem singleton_sublist {a : α} {l} : [a] <+ l ↔ a ∈ l :=
id                                           └┘     
src                                            └┘      
typ                                          └┘     
688  ⟨λ h, subset_of_sublist h (mem_singleton_self _), λ h,
id        └───────────────┘   └────────────────┘       
src        └───────────────┘    └────────────────┘
typ       └───────────────┘   └────────────────┘       
689  let ⟨s, t, e⟩ := mem_split h in e.symm ▸
id   └─┘             └───────┘      └───┘ 
src                   └───────┘       └───┘ 
typ  └─┘             └───────┘      └───┘ 
690    (cons_sublist_cons _ (nil_sublist _)).trans (sublist_append_right _ _)⟩
id      └───────────────┘    └─────────┘    └───┘   └──────────────────┘
src     └───────────────┘    └─────────┘    └───┘   └──────────────────┘
typ     └───────────────┘    └─────────┘    └───┘   └──────────────────┘
691  
692  theorem eq_nil_of_sublist_nil {l : list α} (s : l <+ []) : l = [] :=
id                                      └──┘         └┘ └┘      └┘
src                                     └──┘           └┘ └┘       └┘
typ                                     └──┘         └┘ └┘      └┘
693  eq_nil_of_subset_nil $ subset_of_sublist s
id   └──────────────────┘   └───────────────┘ 
src  └──────────────────┘   └───────────────┘
typ  └──────────────────┘   └───────────────┘ 
694  
695  theorem repeat_sublist_repeat (a : α) {m n} : repeat a m <+ repeat a n ↔ m ≤ n :=
id                                                └────┘   └┘ └────┘      
src                                                └────┘     └┘ └────┘        
typ                                               └────┘   └┘ └────┘      
696  ⟨λ h, by simpa only [length_repeat] using length_le_of_sublist h,
id                       └───────────┘        └──────────────────┘ 
src           └──────────┘└───────────┘└──────┘└──────────────────┘
typ          └──────────┘└───────────┘└──────┘└──────────────────┘
doc           └──────────┘             └──────┘                    
txt           └──────────┘             └──────┘                    
par           └──────────┘             └──────┘                    
pid                └──┘└┘             └────┘                    
st           └──────────────────────────────────────────────────────┘
697   λ h, by induction h; [refl, simp only [*, repeat_succ, sublist.cons]] ⟩
id                                           └─────────┘  └──────────┘
src           └────────┘   └──┘  └────────────┘└─────────┘└┘└──────────┘
typ          └────────┘  └──┘  └────────────┘└─────────┘└┘└──────────┘
doc           └────────┘    └──┘  └────────────┘           └┘            
txt           └────────┘    └──┘  └────────────┘           └┘            
par           └────────┘    └──┘  └────────────┘           └┘            
pid                                  └──┘└───┘           └┘            
st           └────────────────────────────────────────────────────────────┘
698  
699  theorem eq_of_sublist_of_length_eq : ∀ {l₁ l₂ : list α}, l₁ <+ l₂ → length l₁ = length l₂ → l₁ = l₂
id                                                  └──┘    └┘ └┘ └┘   └────┘ └┘  └────┘ └┘   └┘  └┘
src                                                  └──┘        └┘      └────┘     └────┘         
typ                                                 └──┘    └┘ └┘ └┘   └────┘ └┘  └────┘ └┘   └┘  └┘
700  | ._ ._ sublist.slnil             h := rfl
id           └───────────┘                  └─┘
src          └───────────┘                  └─┘
typ          └───────────┘                  └─┘
701  | ._ ._ (sublist.cons  l₁ l₂ a s) h :=
id            └──────────┘          
src           └──────────┘
typ           └──────────┘          
702    absurd (length_le_of_sublist s) $ not_le_of_gt $ by rw h; apply lt_succ_self
id     └────┘  └──────────────────┘      └──────────┘                 └──────────┘
src    └────┘  └──────────────────┘      └──────────┘      └─┘   └────┘└──────────┘
typ    └────┘  └──────────────────┘      └──────────┘      └─┘  └────┘└──────────┘
doc                                                        └─┘   └────┘            
txt                                                        └─┘   └────┘            
par                                                        └─┘   └────┘            
pid                                                                              
st                                                        └────────────────────────┘
703  | ._ ._ (sublist.cons2 l₁ l₂ a s) h :=
id            └───────────┘
src           └───────────┘
typ           └───────────┘
704    by rw [length, length] at h; injection h with h; rw eq_of_sublist_of_length_eq s h
id            └────┘  └────┘                              └────────────────────────┘  
src       └──┘└────┘└┘└────┘└────┘  └────────┘ └─────┘  └─┘                            
typ       └──┘└────┘└┘└────┘└────┘  └────────┘└─────┘  └─┘└────────────────────────┘
doc       └──┘      └┘      └────┘  └────────┘ └─────┘  └─┘                            
txt       └──┘      └┘      └────┘  └────────┘ └─────┘  └─┘                            
par       └──┘      └┘      └────┘  └────────┘ └─────┘  └─┘                            
pid         └┘      └┘      └───┘            └─────┘                                
st       └─────────┘└──────┘└────────────────────────────┘└────────────────────────┘└────
705  
src  
typ  
doc  
txt  
par  
pid  
st   
706  theorem eq_of_sublist_of_length_le {l₁ l₂ : list α} (s : l₁ <+ l₂) (h : length l₂ ≤ length l₁) : l₁ = l₂ :=
id                                               └──┘        └┘ └┘ └┘       └────┘ └┘  └────┘ └┘    └┘  └┘
src                                              └──┘            └┘          └────┘     └────┘          
typ                                              └──┘        └┘ └┘ └┘       └────┘ └┘  └────┘ └┘    └┘  └┘
707  eq_of_sublist_of_length_eq s (le_antisymm (length_le_of_sublist s) h)
id   └────────────────────────┘   └─────────┘  └──────────────────┘   
src  └────────────────────────┘    └─────────┘  └──────────────────┘
typ  └────────────────────────┘   └─────────┘  └──────────────────┘   
708  
709  theorem sublist_antisymm {l₁ l₂ : list α} (s₁ : l₁ <+ l₂) (s₂ : l₂ <+ l₁) : l₁ = l₂ :=
id                                     └──┘         └┘ └┘ └┘        └┘ └┘ └┘    └┘  └┘
src                                    └──┘             └┘              └┘          
typ                                    └──┘         └┘ └┘ └┘        └┘ └┘ └┘    └┘  └┘
710  eq_of_sublist_of_length_le s₁ (length_le_of_sublist s₂)
id   └────────────────────────┘ └┘  └──────────────────┘ └┘
src  └────────────────────────┘     └──────────────────┘
typ  └────────────────────────┘ └┘  └──────────────────┘ └┘
711  
712  instance decidable_sublist [decidable_eq α] : ∀ (l₁ l₂ : list α), decidable (l₁ <+ l₂)
id                               └──────────┘               └──┘    └───────┘  └┘ └┘ └┘
src                              └──────────┘                 └──┘     └───────┘     └┘
typ                              └──────────┘               └──┘    └───────┘  └┘ └┘ └┘
713  | []      l₂      := is_true $ nil_sublist _
id     └┘                 └─────┘   └─────────┘
src    └┘                 └─────┘   └─────────┘
typ    └┘                 └─────┘   └─────────┘
714  | (a::l₁) []      := is_false $ λh, list.no_confusion $ eq_nil_of_sublist_nil h
id       └┘    └┘         └──────┘      └───────────────┘   └───────────────────┘ 
src      └┘    └┘         └──────┘       └───────────────┘   └───────────────────┘
typ      └┘    └┘         └──────┘      └───────────────┘   └───────────────────┘ 
715  | (a::l₁) (b::l₂) :=
id      └┘└┘   └┘└┘
src      └┘      └┘
typ     └┘└┘   └┘└┘
716    if h : a = b then
id     └┘       
src    └┘       
typ    └┘       
717      decidable_of_decidable_of_iff (decidable_sublist l₁ l₂) $
id       └───────────────────────────┘  └───────────────┘
src      └───────────────────────────┘
typ      └───────────────────────────┘  └───────────────┘
718        by rw [← h]; exact ⟨cons_sublist_cons _, sublist_of_cons_sublist_cons⟩
id                            └───────────────┘    └──────────────────────────┘
src           └────┘   └────┘ └───────────────┘└──┘└──────────────────────────┘└─
typ           └────┘  └────┘ └───────────────┘└──┘└──────────────────────────┘└─
doc           └────┘   └────┘                  └──┘                            └─
txt           └────┘   └────┘                  └──┘                            └─
par           └────┘   └────┘                  └──┘                            └─
pid             └──┘                          └──┘                            
st           └──────┘└───────────────────────────────────────────────────────────
719    else decidable_of_decidable_of_iff (decidable_sublist (a::l₁) l₂)
id          └───────────────────────────┘  └───────────────┘   └┘
src  ─┘     └───────────────────────────┘                      └┘
typ  ─┘     └───────────────────────────┘  └───────────────┘   └┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘
720      ⟨sublist_cons_of_sublist _, λs, match a, l₁, s, h with
id        └─────────────────────┘                      
src       └─────────────────────┘
typ       └─────────────────────┘                      
721      | a, l₁, sublist.cons ._ ._ ._ s', h := s'
id                └──────────┘          └┘
src               └──────────┘
typ               └──────────┘          └┘
722      | ._, ._, sublist.cons2 t ._ ._ s', h := absurd rfl h
id                 └───────────┘                 └────┘ └─┘
src                └───────────┘                  └────┘ └─┘
typ                └───────────┘                 └────┘ └─┘
723      end⟩
724  
725  /- index_of -/
726  
727  section index_of
728  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
729  
730  @[simp] theorem index_of_nil (a : α) : index_of a [] = 0 := rfl
id                                         └──────┘  └┘       └─┘
src                                         └──────┘   └┘       └─┘
typ                                        └──────┘  └┘       └─┘
doc    └──┘
731  
732  theorem index_of_cons (a b : α) (l : list α) : index_of a (b::l) = if a = b then 0 else succ (index_of a l) := rfl
id                                       └──┘     └──────┘   └┘                     └──┘  └──────┘       └─┘
src                                       └──┘      └──────┘     └┘                        └──┘  └──────┘         └─┘
typ                                      └──┘     └──────┘   └┘                     └──┘  └──────┘       └─┘
733  
734  theorem index_of_cons_eq {a b : α} (l : list α) : a = b → index_of a (b::l) = 0 :=
id                                          └──┘          └──────┘   └┘  
src                                          └──┘             └──────┘     └┘   
typ                                         └──┘          └──────┘   └┘  
735  assume e, if_pos e
id            └────┘ 
src            └────┘
typ           └────┘ 
736  
737  @[simp] theorem index_of_cons_self (a : α) (l : list α) : index_of a (a::l) = 0 :=
id                                                  └──┘     └──────┘   └┘  
src                                                  └──┘      └──────┘     └┘   
typ                                                 └──┘     └──────┘   └┘  
doc    └──┘
738  index_of_cons_eq _ rfl
id   └──────────────┘   └─┘
src  └──────────────┘   └─┘
typ  └──────────────┘   └─┘
739  
740  @[simp] theorem index_of_cons_ne {a b : α} (l : list α) : a ≠ b → index_of a (b::l) = succ (index_of a l) :=
id                                                  └──┘          └──────┘   └┘   └──┘  └──────┘  
src                                                  └──┘             └──────┘     └┘    └──┘  └──────┘
typ                                                 └──┘          └──────┘   └┘   └──┘  └──────┘  
doc    └──┘
741  assume n, if_neg n
id            └────┘ 
src            └────┘
typ           └────┘ 
742  
743  theorem index_of_eq_length {a : α} {l : list α} : index_of a l = length l ↔ a ∉ l :=
id                                          └──┘     └──────┘    └────┘     
src                                          └──┘      └──────┘      └────┘      
typ                                         └──┘     └──────┘    └────┘     
744  begin
st   └─────
745    induction l with b l ih,
id               
src    └────────┘ └──────────┘
typ    └────────┘└──────────┘
doc    └────────┘ └──────────┘
txt    └────────┘ └──────────┘
par    └────────┘ └──────────┘
pid              └─────────┘
st   ────────────────────────┘└─
746    { exact iff_of_true rfl (not_mem_nil _) },
id             └─────────┘ └─┘  └─────────┘
src      └────┘└─────────┘└─┘ └─────────┘└──┘
typ      └────┘└─────────┘└─┘ └─────────┘└──┘
doc      └────┘                          └──┘
txt      └────┘                          └──┘
par      └────┘                          └──┘
pid                                     └─┘
st   ───┘└────────────────────────────────────┘└┘
747    simp only [length, mem_cons_iff, index_of_cons], split_ifs,
id                └────┘  └──────────┘  └───────────┘
src    └─────────┘└────┘└┘└──────────┘└┘└───────────┘  └───────┘
typ    └─────────┘└────┘└┘└──────────┘└┘└───────────┘  └───────┘
doc    └─────────┘      └┘            └┘               └───────┘
txt    └─────────┘      └┘            └┘               └───────┘
par    └─────────┘      └┘            └┘               └───────┘
pid        └──┘└┘      └┘            └┘             
st   ────────────────────────────────────────────────┘└─────────┘└─
748    { exact iff_of_false (by rintro ⟨⟩) (λ H, H $ or.inl h) },
id             └──────────┘                          └────┘ 
src      └────┘└──────────┘   └───────┘└┘  └──┘  └────┘ └┘
typ      └────┘└──────────┘   └───────┘└┘  └──┘  └────┘└┘
doc      └────┘               └───────┘└┘  └──┘         └┘
txt      └────┘               └───────┘└┘  └──┘         └┘
par      └────┘               └───────┘└┘  └──┘         └┘
pid                          └──────────┘  └──┘         
st   ───┘└────────────────────┘└────────┘└────────────────────┘└┘
749    { simp only [h, false_or], rw ← ih, exact succ_inj' }
id                    └──────┘        └┘        └───────┘
src      └─────────┘ └┘└──────┘  └───┘    └────┘└───────┘
typ      └─────────┘└┘└──────┘  └───┘└┘  └────┘└───────┘
doc      └─────────┘ └┘          └───┘    └────┘         
txt      └─────────┘ └┘          └───┘    └────┘         
par      └─────────┘ └┘          └───┘    └────┘         
pid          └──┘└┘ └┘            └─┘                  
st   ──────────────────────────┘└───────┘└────────────────┘└─
750  end
st   ──┘
751  
752  @[simp] theorem index_of_of_not_mem {l : list α} {a : α} : a ∉ l → index_of a l = length l :=
id                                            └──┘                 └──────┘    └────┘ 
src                                           └──┘                     └──────┘      └────┘
typ                                           └──┘                 └──────┘    └────┘ 
doc    └──┘
753  index_of_eq_length.2
id   └────────────────┘
src  └────────────────┘
typ  └────────────────┘
754  
755  theorem index_of_le_length {a : α} {l : list α} : index_of a l ≤ length l :=
id                                          └──┘     └──────┘    └────┘ 
src                                          └──┘      └──────┘      └────┘
typ                                         └──┘     └──────┘    └────┘ 
756  begin
st   └─────
757    induction l with b l ih, {refl},
id               
src    └────────┘ └──────────┘   └──┘
typ    └────────┘└──────────┘   └──┘
doc    └────────┘ └──────────┘   └──┘
txt    └────────┘ └──────────┘   └──┘
par    └────────┘ └──────────┘   └──┘
pid              └─────────┘
st   ────────────────────────┘└─────┘└┘
758    simp only [length, index_of_cons],
id                └────┘  └───────────┘
src    └─────────┘└────┘└┘└───────────┘
typ    └─────────┘└────┘└┘└───────────┘
doc    └─────────┘      └┘             
txt    └─────────┘      └┘             
par    └─────────┘      └┘             
pid        └──┘└┘      └┘             
st   ──────────────────────────────────┘└─
759    by_cases h : a = b, {rw if_pos h, exact nat.zero_le _},
id                          └────┘         └─────────┘
src    └───────┘ └─┘     └─┘└────┘   └────┘└─────────┘└┘
typ    └───────┘ └─┘   └─┘└────┘  └────┘└─────────┘└┘
doc    └───────┘ └─┘      └─┘         └────┘           └┘
txt    └───────┘ └─┘      └─┘         └────┘           └┘
par    └───────┘ └─┘      └─┘         └────┘           └┘
pid             └─┘                                 └┘
st   ───────────────────┘└────┘└────┘└┘└───────────────────┘└┘
760    rw if_neg h, exact succ_le_succ ih
id        └────┘         └──────────┘ └┘
src    └─┘└────┘   └────┘└──────────┘  
typ    └─┘└────┘  └────┘└──────────┘└┘
doc    └─┘         └────┘              
txt    └─┘         └────┘              
par    └─┘         └────┘              
pid                                  
st   ────────────┘└──────────────────────┘
761  end
st   └─┘
762  
763  theorem index_of_lt_length {a} {l : list α} : index_of a l < length l ↔ a ∈ l :=
id                                       └──┘     └──────┘    └────┘     
src                                      └──┘      └──────┘      └────┘      
typ                                      └──┘     └──────┘    └────┘     
764  ⟨λh, by_contradiction $ λ al, ne_of_lt h $ index_of_eq_length.2 al,
id       └──────────────┘     └┘  └──────┘    └────────────────┘  └┘
src       └──────────────┘         └──────┘     └────────────────┘
typ      └──────────────┘     └┘  └──────┘    └────────────────┘  └┘
765  λal, lt_of_le_of_ne index_of_le_length $ λ h, index_of_eq_length.1 h al⟩
id    └┘  └────────────┘ └────────────────┘       └────────────────┘   └┘
src       └────────────┘ └────────────────┘        └────────────────┘
typ   └┘  └────────────┘ └────────────────┘       └────────────────┘   └┘
766  
767  end index_of
768  
769  /- nth element -/
770  
771  theorem nth_le_of_mem : ∀ {a} {l : list α}, a ∈ l → ∃ n h, nth_le l n h = a
id                                    └──┘            └────┘     
src                                     └──┘                 └────┘       
typ                                   └──┘            └────┘     
772  | a (_ :: l) (or.inl rfl) := ⟨0, succ_pos _, rfl⟩
id          └┘     └────┘ └─┘         └──────┘    └─┘
src         └┘     └────┘ └─┘         └──────┘    └─┘
typ         └┘     └────┘ └─┘         └──────┘    └─┘
773  | a (b :: l) (or.inr m)   :=
id          └┘     └────┘ 
src         └┘     └────┘
typ         └┘     └────┘ 
774    let ⟨n, h, e⟩ := nth_le_of_mem m in ⟨n+1, succ_lt_succ h, e⟩
id     └─┘           └───────────┘           └──────────┘
src                                             └──────────┘
typ    └─┘           └───────────┘           └──────────┘
775  
776  theorem nth_le_nth : ∀ {l : list α} {n} h, nth l n = some (nth_le l n h)
id                              └──┘        └─┘    └──┘  └────┘   
src                              └──┘           └─┘      └──┘  └────┘
typ                             └──┘        └─┘    └──┘  └────┘   
777  | (a :: l) 0     h := rfl
id        └┘               └─┘
src       └┘               └─┘
typ       └┘               └─┘
778  | (a :: l) (n+1) h := @nth_le_nth l n _
id        └┘             └────────┘
src       └┘      
typ       └┘             └────────┘
779  
780  theorem nth_len_le : ∀ {l : list α} {n}, length l ≤ n → nth l n = none
id                              └──┘       └────┘      └─┘    └──┘
src                              └──┘         └────┘        └─┘      └──┘
typ                             └──┘       └────┘      └─┘    └──┘
781  | []       n     h := rfl
id     └┘                  └─┘
src    └┘                  └─┘
typ    └┘                  └─┘
782  | (a :: l) (n+1) h := nth_len_le (le_of_succ_le_succ h)
id        └┘             └────────┘  └────────────────┘
src       └┘                          └────────────────┘
typ       └┘             └────────┘  └────────────────┘
783  
784  theorem nth_eq_some {l : list α} {n a} : nth l n = some a ↔ ∃ h, nth_le l n h = a :=
id                            └──┘           └─┘    └──┘     └────┘     
src                           └──┘            └─┘      └──┘       └────┘       
typ                           └──┘           └─┘    └──┘     └────┘     
785  ⟨λ e,
id      
typ     
786    have h : n < length l, from lt_of_not_ge $ λ hn,
id                └────┘        └──────────┘     └┘
src                └────┘         └──────────┘
typ               └────┘        └──────────┘     └┘
787      by rw nth_len_le hn at e; contradiction,
id             └────────┘ └┘
src         └─┘└────────┘  └───┘  └───────────┘
typ         └─┘└────────┘└┘└───┘  └───────────┘
doc         └─┘            └───┘  └───────────┘
txt         └─┘            └───┘  └───────────┘
par         └─┘            └───┘  └───────────┘
pid                       └───┘
st         └───────────────────────────────────┘
788    ⟨h, by rw nth_le_nth h at e;
id              └────────┘ 
src           └─┘└────────┘ └───┘
typ          └─┘└────────┘└───┘
doc           └─┘           └───┘
txt           └─┘           └───┘
par           └─┘           └───┘
pid                        └───┘
st           └──────────────────────
789      injection e with e; apply nth_le_mem⟩,
id                 
src      └────────┘ └─────┘  └────┘
typ      └────────┘└─────┘  └────┘
doc      └────────┘ └─────┘  └────┘
txt      └────────┘ └─────┘  └────┘
par      └────────┘ └─────┘  └────┘
pid                └─────┘       
st   ───────────────────────────────────────┘
790  λ ⟨h, e⟩, e ▸ nth_le_nth _⟩
id              └────────┘
src               └────────┘
typ             └────────┘
791  
792  theorem nth_of_mem {a} {l : list α} (h : a ∈ l) : ∃ n, nth l n = some a :=
id                               └──┘                └─┘    └──┘ 
src                              └──┘                    └─┘      └──┘
typ                              └──┘                └─┘    └──┘ 
793  let ⟨n, h, e⟩ := nth_le_of_mem h in ⟨n, by rw [nth_le_nth, e]⟩
id   └─┘             └───────────┘                └────────┘  
src                   └───────────┘             └──┘└────────┘└┘ 
typ  └─┘             └───────────┘            └──┘└────────┘└┘
doc                                             └──┘          └┘ 
txt                                             └──┘          └┘ 
par                                             └──┘          └┘ 
pid                                               └┘          └┘ 
st                                             └─────────────┘└─┘
794  
795  theorem nth_le_mem : ∀ (l : list α) n h, nth_le l n h ∈ l
id                              └──┘      └────┘     
src                              └──┘         └────┘       
typ                             └──┘      └────┘     
796  | (a :: l) 0     h := mem_cons_self _ _
id        └┘               └───────────┘
src       └┘               └───────────┘
typ       └┘               └───────────┘
797  | (a :: l) (n+1) h := mem_cons_of_mem _ (nth_le_mem l _ _)
id        └┘             └─────────────┘    └────────┘
src       └┘              └─────────────┘
typ       └┘             └─────────────┘    └────────┘
798  
799  theorem nth_mem {l : list α} {n a} (e : nth l n = some a) : a ∈ l :=
id                        └──┘              └─┘    └──┘       
src                       └──┘               └─┘      └──┘        
typ                       └──┘              └─┘    └──┘       
800  let ⟨h, e⟩ := nth_eq_some.1 e in e ▸ nth_le_mem _ _ _
id   └─┘          └─────────┘         └────────┘
src                └─────────┘          └────────┘
typ  └─┘          └─────────┘         └────────┘
801  
802  theorem mem_iff_nth_le {a} {l : list α} : a ∈ l ↔ ∃ n h, nth_le l n h = a :=
id                                   └──┘            └────┘     
src                                  └──┘                 └────┘       
typ                                  └──┘            └────┘     
803  ⟨nth_le_of_mem, λ ⟨n, h, e⟩, e ▸ nth_le_mem _ _ _⟩
id    └───────────┘                └────────┘
src   └───────────┘                  └────────┘
typ   └───────────┘                └────────┘
804  
805  theorem mem_iff_nth {a} {l : list α} : a ∈ l ↔ ∃ n, nth l n = some a :=
id                                └──┘           └─┘    └──┘ 
src                               └──┘               └─┘      └──┘
typ                               └──┘           └─┘    └──┘ 
806  mem_iff_nth_le.trans $ exists_congr $ λ n, nth_eq_some.symm
id   └────────────┘└────┘   └──────────┘       └─────────┘└───┘
src  └────────────┘└────┘   └──────────┘        └─────────┘└───┘
typ  └────────────┘└────┘   └──────────┘       └─────────┘└───┘
807  
808  @[simp] theorem nth_map (f : α → β) : ∀ l n, nth (map f l) n = (nth l n).map f
id                                            └─┘  └─┘       └─┘   └─┘  
src                                               └─┘  └─┘          └─┘     └─┘
typ                                           └─┘  └─┘       └─┘   └─┘  
doc    └──┘
809  | []       n     := rfl
id     └┘                └─┘
src    └┘                └─┘
typ    └┘                └─┘
810  | (a :: l) 0     := rfl
id        └┘             └─┘
src       └┘             └─┘
typ       └┘             └─┘
811  | (a :: l) (n+1) := nth_map l n
id        └┘          └─────┘
src       └┘      
typ       └┘          └─────┘
812  
813  theorem nth_le_map (f : α → β) {l n} (H1 H2) : nth_le (map f l) n H1 = f (nth_le l n H2) :=
id                                                └────┘  └─┘     └┘    └────┘   └┘
src                                                 └────┘  └─┘               └────┘
typ                                               └────┘  └─┘     └┘    └────┘   └┘
814  option.some.inj $ by rw [← nth_le_nth, nth_map, nth_le_nth]; refl
id   └─────────────┘            └────────┘  └─────┘  └────────┘
src  └─────────────┘      └────┘└────────┘└┘└─────┘└┘└────────┘  └────
typ  └─────────────┘      └────┘└────────┘└┘└─────┘└┘└────────┘  └────
doc                       └────┘          └┘       └┘            └────
txt                       └────┘          └┘       └┘            └────
par                       └────┘          └┘       └┘            └────
pid                         └──┘          └┘       └┘                
st                       └───────────────┘└───────┘└──────────┘└──────
815  
src  
typ  
doc  
txt  
par  
pid  
st   
816  /-- A version of `nth_le_map` that can be used for rewriting. -/
817  theorem nth_le_map_rev (f : α → β) {l n} (H) :
id                                  
typ                                 
818    f (nth_le l n H) = nth_le (map f l) n ((length_map f l).symm ▸ H) :=
id       └────┘      └────┘  └─┘       └────────┘   └──┘   
src       └────┘         └────┘  └─┘          └────────┘     └──┘  
typ      └────┘      └────┘  └─┘       └────────┘   └──┘   
819  (nth_le_map f _ _).symm
id    └────────┘      └──┘
src   └────────┘       └──┘
typ   └────────┘      └──┘
820  
821  @[simp] theorem nth_le_map' (f : α → β) {l n} (H) :
id                                       
typ                                      
doc    └──┘
822    nth_le (map f l) n H = f (nth_le l n (length_map f l ▸ H)) :=
id     └────┘  └─┘         └────┘    └────────┘    
src    └────┘  └─┘              └────┘      └────────┘     
typ    └────┘  └─┘         └────┘    └────────┘    
823  nth_le_map f _ _
id   └────────┘ 
src  └────────┘
typ  └────────┘ 
824  
825  @[simp] lemma nth_le_singleton (a : α) {n : ℕ} (hn : n < 1) :
id                                                       
src                                                        
typ                                                      
doc    └──┘
826    nth_le [a] n hn = a :=
id     └────┘   └┘  
src    └────┘        
typ    └────┘   └┘  
827  have hn0 : n = 0 := le_zero_iff.1 (le_of_lt_succ hn),
id                     └─────────┘   └───────────┘ └┘
src                     └─────────┘   └───────────┘
typ                    └─────────┘   └───────────┘ └┘
828  by subst hn0; refl
id            └─┘
src     └────┘     └────
typ     └────┘└─┘  └────
doc     └────┘     └────
txt     └────┘     └────
par     └────┘     └────
pid                   
st     └────────────────
829  
src  
typ  
doc  
txt  
par  
pid  
st   
830  lemma nth_le_append : ∀ {l₁ l₂ : list α} {n : ℕ} (hn₁) (hn₂),
id                                   └──┘           └─┘   └─┘
src                                   └──┘         
typ                                  └──┘           └─┘   └─┘
831    (l₁ ++ l₂).nth_le n hn₁ = l₁.nth_le n hn₂
id      └┘ └┘ └┘ └────┘   └─┘  └┘└─────┘  └─┘
src        └┘    └────┘           └─────┘
typ     └┘ └┘ └┘ └────┘   └─┘  └┘└─────┘  └─┘
832  | []     _ n     hn₁ hn₂  := (not_lt_zero _ hn₂).elim
id     └┘                 └─┘      └─────────┘       └──┘
src    └┘                          └─────────┘       └──┘
typ    └┘                 └─┘      └─────────┘       └──┘
833  | (a::l) _ 0     hn₁ hn₂ := rfl
id       └┘                      └─┘
src      └┘                      └─┘
typ      └┘                      └─┘
834  | (a::l) _ (n+1) hn₁ hn₂ := by simp only [nth_le, cons_append];
id       └┘                                   └────┘  └─────────┘
src      └┘                        └─────────┘└────┘└┘└─────────┘
typ      └┘                        └─────────┘└────┘└┘└─────────┘
doc                                 └─────────┘      └┘           
txt                                 └─────────┘      └┘           
par                                 └─────────┘      └┘           
pid                                     └──┘└┘      └┘           
st                                 └─────────────────────────────────
835                           exact nth_le_append _ _
id                                  └───────────┘
src                           └────┘             └────
typ                           └────┘└───────────┘└────
doc                           └────┘             └────
txt                           └────┘             └────
par                           └────┘             └────
pid                                             └──┘
st   ─────────────────────────────────────────────────
836  
src  
typ  
doc  
txt  
par  
pid  
st   
837  lemma nth_le_append_right_aux {l₁ l₂ : list α} {n : ℕ}
id                                          └──┘        
src                                         └──┘         
typ                                         └──┘        
838    (h₁ : l₁.length ≤ n) (h₂ : n < (l₁ ++ l₂).length) : n - l₁.length < l₂.length :=
id           └┘└─────┘             └┘ └┘ └┘ └────┘       └┘└─────┘  └┘└─────┘
src            └─────┘                  └┘    └────┘          └─────┘    └─────┘
typ          └┘└─────┘             └┘ └┘ └┘ └────┘       └┘└─────┘  └┘└─────┘
839  begin
st   └─────
840    rw list.length_append at h₂,
id        └────────────────┘
src    └─┘└────────────────┘└────┘
typ    └─┘└────────────────┘└────┘
doc    └─┘                  └────┘
txt    └─┘                  └────┘
par    └─┘                  └────┘
pid                        └────┘
st   ────────────────────────────┘└─
841    convert (nat.sub_lt_sub_right_iff h₁).mpr h₂,
id              └──────────────────────┘ └┘      └┘
src    └──────┘ └──────────────────────┘  └────┘
typ    └──────┘ └──────────────────────┘└┘└────┘└┘
doc    └──────┘                           └────┘
txt    └──────┘                           └────┘
par    └──────┘                           └────┘
pid                                      └────┘
st   ─────────────────────────────────────────────┘└─
842    simp,
src    └──┘
typ    └──┘
doc    └──┘
txt    └──┘
par    └──┘
st   ─────┘└─
843  end
st   ──┘
844  
845  lemma nth_le_append_right : ∀ {l₁ l₂ : list α} {n : ℕ} (h₁ : l₁.length ≤ n) (h₂),
id                                         └──┘                └┘└─────┘     └┘
src                                         └──┘                   └─────┘ 
typ                                        └──┘                └┘└─────┘     └┘
846    (l₁ ++ l₂).nth_le n h₂ = l₂.nth_le (n - l₁.length) (nth_le_append_right_aux h₁ h₂)
id      └┘ └┘ └┘ └────┘   └┘  └┘└─────┘    └┘└─────┘   └─────────────────────┘ └┘ └┘
src        └┘    └────┘          └─────┘       └─────┘   └─────────────────────┘
typ     └┘ └┘ └┘ └────┘   └┘  └┘└─────┘    └┘└─────┘   └─────────────────────┘ └┘ └┘
847  | []       _ n     h₁ h₂ := rfl
id     └┘                        └─┘
src    └┘                        └─┘
typ    └┘                        └─┘
848  | (a :: l) _ (n+1) h₁ h₂ :=
id        └┘        
src       └┘        
typ       └┘        
849    begin
st     └─────
850      dsimp,
src      └───┘
typ      └───┘
doc      └───┘
txt      └───┘
par      └───┘
st   ────────┘└─
851      conv { to_rhs, congr, skip, rw [←nat.sub_sub, nat.sub.right_comm, nat.add_sub_cancel], },
id                                        └─────────┘  └────────────────┘  └────────────────┘
src      └─────┘└────┘└┘└───┘└┘└──┘└┘└───┘└─────────┘└┘└────────────────┘└┘└────────────────┘└─┘
typ      └─────┘└────┘└┘└───┘└┘└──┘└┘└───┘└─────────┘└┘└────────────────┘└┘└────────────────┘└─┘
txt      └─────┘└────┘└┘└───┘└┘└──┘└┘└───┘           └┘                  └┘                  └─┘
par      └─────┘└────┘└┘└───┘└┘└──┘└┘└───┘           └┘                  └┘                  └─┘
pid          └──────────────────────────┘           └┘                  └┘                  └──┘
st   ─────────┘└─────┘└─────┘└────┘└────────────────┘└──────────────────┘└──────────────────┘ └──┘
852      rw nth_le_append_right (nat.lt_succ_iff.mp h₁),
id          └─────────────────┘  └────────────────┘ └┘
src      └─┘                    └────────────────┘  
typ      └─┘└─────────────────┘ └────────────────┘└┘
doc      └─┘                                        
txt      └─┘                                        
par      └─┘                                        
pid                                                
st   ─────────────────────────────────────────────────┘└─
853    end
st   ────┘
854  
855  @[simp] lemma nth_le_repeat (a : α) {n m : ℕ} (h : m < n) :
id                                                      
src                                                      
typ                                                     
doc    └──┘
856    (list.repeat a n).nth_le m (by rwa list.length_repeat) = a :=
id      └─────────┘   └────┘           └────────────────┘   
src     └─────────┘     └────┘        └──┘└────────────────┘  
typ     └─────────┘   └────┘       └──┘└────────────────┘   
doc                                   └──┘
txt                                   └──┘
par                                   └──┘
pid                                      
st                                   └─────────────────────┘
857  eq_of_mem_repeat (nth_le_mem _ _ _)
id   └──────────────┘  └────────┘
src  └──────────────┘  └────────┘
typ  └──────────────┘  └────────┘
858  
859  lemma nth_append  {l₁ l₂ : list α} {n : ℕ} (hn : n < l₁.length) :
id                              └──┘                  └┘└─────┘
src                             └──┘                      └─────┘
typ                             └──┘                  └┘└─────┘
860    (l₁ ++ l₂).nth n = l₁.nth n :=
id      └┘ └┘ └┘ └─┘    └┘└──┘ 
src        └┘    └─┘       └──┘
typ     └┘ └┘ └┘ └─┘    └┘└──┘ 
861  have hn' : n < (l₁ ++ l₂).length := lt_of_lt_of_le hn
id                 └┘ └┘ └┘ └────┘     └────────────┘ └┘
src                    └┘    └────┘     └────────────┘
typ                └┘ └┘ └┘ └────┘     └────────────┘ └┘
862    (by rw length_append; exact le_add_right _ _),
id            └───────────┘        └──────────┘
src        └─┘└───────────┘  └────┘└──────────┘└──┘
typ        └─┘└───────────┘  └────┘└──────────┘└──┘
doc        └─┘               └────┘            └──┘
txt        └─┘               └────┘            └──┘
par        └─┘               └────┘            └──┘
pid                                          └──┘
st        └───────────────────────────────────────┘
863  by rw [nth_le_nth hn, nth_le_nth hn', nth_le_append]
id          └────────┘ └┘  └────────┘ └─┘  └───────────┘
src     └──┘└────────┘  └┘└────────┘   └┘└───────────┘└─
typ     └──┘└────────┘└┘└┘└────────┘└─┘└┘└───────────┘└─
doc     └──┘            └┘             └┘             └─
txt     └──┘            └┘             └┘             └─
par     └──┘            └┘             └┘             └─
pid       └┘            └┘             └┘             
st     └────────────────┘└──────────────┘└─────────────┘
864  
src  
typ  
doc  
txt  
par  
pid  
st   
865  lemma last_eq_nth_le : ∀ (l : list α) (h : l ≠ []),
id                                └──┘          └┘
src                                └──┘            └┘
typ                               └──┘          └┘
866    last l h = l.nth_le (l.length - 1) (sub_lt (length_pos_of_ne_nil h) one_pos)
id     └──┘    └─────┘  └─────┘      └────┘  └──────────────────┘   └─────┘
src    └──┘       └─────┘   └─────┘      └────┘  └──────────────────┘    └─────┘
typ    └──┘    └─────┘  └─────┘      └────┘  └──────────────────┘   └─────┘
867  | [] h := rfl
id     └┘      └─┘
src    └┘      └─┘
typ    └┘      └─┘
868  | [a] h := by rw [last_singleton, nth_le_singleton]
id                   └────────────┘  └──────────────┘
src              └──┘└────────────┘└┘└──────────────┘└┘
typ              └──┘└────────────┘└┘└──────────────┘└┘
doc                └──┘              └┘                └┘
txt                └──┘              └┘                └┘
par                └──┘              └┘                └┘
pid                  └┘              └┘                
st                └─────────────────┘└────────────────┘
869  | (a :: b :: l) h := by { rw [last_cons, last_eq_nth_le (b :: l)],
id        └┘   └┘                  └───────┘  └────────────┘      
src       └┘   └┘              └──┘└───────┘└┘                   └┘
typ       └┘   └┘              └──┘└───────┘└┘└────────────┘   └┘
doc                            └──┘         └┘                   └┘
txt                            └──┘         └┘                   └┘
par                            └──┘         └┘                   └┘
pid                              └┘         └┘                   └┘
st                          └──────────────┘└───────────────────────┘└──
870                            refl, exact cons_ne_nil b l }
id                                         └─────────┘  
src                            └──┘  └────┘└─────────┘  
typ                            └──┘  └────┘└─────────┘
doc                            └──┘  └────┘             
txt                            └──┘  └────┘             
par                            └──┘  └────┘             
pid                                                    
st   ─────────────────────────────┘└──────────────────────┘└┘
871  
872  @[simp] lemma nth_concat_length: ∀ (l : list α) (a : α), (l ++ [a]).nth l.length = a
id                                          └──┘             └┘  └─┘  └─────┘  
src                                          └──┘                └┘   └─┘   └─────┘ 
typ                                         └──┘             └┘  └─┘  └─────┘  
doc    └──┘
873  | []     a := rfl
id     └┘          └─┘
src    └┘          └─┘
typ    └┘          └─┘
874  | (b::l) a := by rw [cons_append, length_cons, nth, nth_concat_length]
id       └┘               └─────────┘  └─────────┘  └─┘  └───────────────┘
src      └┘           └──┘└─────────┘└┘└─────────┘└┘└─┘└┘                 └─
typ      └┘           └──┘└─────────┘└┘└─────────┘└┘└─┘└┘└───────────────┘└─
doc                   └──┘           └┘           └┘   └┘                 └─
txt                   └──┘           └┘           └┘   └┘                 └─
par                   └──┘           └┘           └┘   └┘                 └─
pid                     └┘           └┘           └┘   └┘                 
st                   └──────────────┘└───────────┘└───┘└─────────────────┘
875  
src  
typ  
doc  
txt  
par  
pid  
st   
876  @[ext]
doc    └─┘
877  theorem ext : ∀ {l₁ l₂ : list α}, (∀n, nth l₁ n = nth l₂ n) → l₁ = l₂
id                           └──┘        └─┘ └┘   └─┘ └┘     └┘  └┘
src                           └──┘          └─┘       └─┘            
typ                          └──┘        └─┘ └┘   └─┘ └┘     └┘  └┘
878  | []      []       h := rfl
id     └┘      └┘            └─┘
src    └┘      └┘            └─┘
typ    └┘      └┘            └─┘
879  | (a::l₁) []       h := by have h0 := h 0; contradiction
id       └┘    └┘                          
src      └┘    └┘               └─────────┘ └┘  └────────────┘
typ      └┘    └┘               └─────────┘└┘  └────────────┘
doc                             └─────────┘ └┘  └────────────┘
txt                             └─────────┘ └┘  └────────────┘
par                             └─────────┘ └┘  └────────────┘
pid                             └─────┘└─┘                
st                             └─────────────────────────────┘
880  | []      (a'::l₂) h := by have h0 := h 0; contradiction
id     └┘         └┘                       
src    └┘         └┘            └─────────┘ └┘  └────────────┘
typ    └┘         └┘            └─────────┘└┘  └────────────┘
doc                             └─────────┘ └┘  └────────────┘
txt                             └─────────┘ └┘  └────────────┘
par                             └─────────┘ └┘  └────────────┘
pid                             └─────┘└─┘                
st                             └─────────────────────────────┘
881  | (a::l₁) (a'::l₂) h := by have h0 : some a = some a' := h 0; injection h0 with aa;
id       └┘       └┘                             └──┘ └┘                  └┘
src      └┘       └┘            └────────┘     └──┘  └──┘ └┘  └────────┘  └──────┘
typ      └┘       └┘            └────────┘    └──┘└┘└──┘└┘  └────────┘└┘└──────┘
doc                             └────────┘            └──┘ └┘  └────────┘  └──────┘
txt                             └────────┘            └──┘ └┘  └────────┘  └──────┘
par                             └────────┘            └──┘ └┘  └────────┘  └──────┘
pid                             └─────┘└─┘            └──┘              └──────┘
st                             └─────────────────────────────────────────────────────────
882      simp only [aa, ext (λn, h (n+1))]; split; refl
id                  └┘  └─┘         
src      └─────────┘  └┘     └─┘   └──┘  └───┘  └────
typ      └─────────┘└┘└┘└─┘  └─┘  └──┘  └───┘  └────
doc      └─────────┘  └┘     └─┘    └──┘  └───┘  └────
txt      └─────────┘  └┘     └─┘    └──┘  └───┘  └────
par      └─────────┘  └┘     └─┘    └──┘  └───┘  └────
pid          └──┘└┘  └┘     └─┘    └──┘             
st   ───────────────────────────────────────────────────
883  
src  
typ  
doc  
txt  
par  
pid  
st   
884  theorem ext_le {l₁ l₂ : list α} (hl : length l₁ = length l₂) (h : ∀n h₁ h₂, nth_le l₁ n h₁ = nth_le l₂ n h₂) : l₁ = l₂ :=
id                           └──┘         └────┘ └┘  └────┘ └┘         └┘ └┘  └────┘ └┘  └┘  └────┘ └┘  └┘    └┘  └┘
src                          └──┘          └────┘     └────┘                    └────┘          └────┘               
typ                          └──┘         └────┘ └┘  └────┘ └┘         └┘ └┘  └────┘ └┘  └┘  └────┘ └┘  └┘    └┘  └┘
885  ext $ λn, if h₁ : n < length l₁
id   └─┘      └┘        └────┘ └┘
src  └─┘       └┘         └────┘
typ  └─┘      └┘        └────┘ └┘
886    then by rw [nth_le_nth, nth_le_nth, h n h₁ (by rwa [← hl])]
id                 └────────┘  └────────┘    └┘            └┘
src            └──┘└────────┘└┘└────────┘└┘       └─────┘  └──
typ            └──┘└────────┘└┘└────────┘└┘└┘   └──────┘└┘└───
doc            └──┘          └┘          └┘       └─────┘  └──
txt            └──┘          └┘          └┘       └─────┘  └──
par            └──┘          └┘          └┘       └──────┘  └───
pid              └┘          └┘          └┘       └──────┘  └─┘
st            └─────────────┘└──────────┘└──────────┘└────────┘
887    else let h₁ := le_of_not_gt h₁ in by { rw [nth_len_le h₁, nth_len_le], rwa [←hl], }
id          └─┘ └┘    └──────────┘ └┘             └────────┘ └┘  └────────┘         └┘
src  ─┘               └──────────┘            └──┘└────────┘  └┘└────────┘  └────┘  
typ  ─┘     └─┘ └┘    └──────────┘ └┘         └──┘└────────┘└┘└┘└────────┘  └────┘└┘
doc  ─┘                                       └──┘            └┘            └────┘  
txt  ─┘                                       └──┘            └┘            └────┘  
par  ─┘                                       └──┘            └┘            └────┘  
pid  ─┘                                         └┘            └┘               └─┘  
st   ─┘                                    └──────────────────┘└──────────┘└─────────┘└──┘
888  
889  @[simp] theorem index_of_nth_le [decidable_eq α] {a : α} : ∀ {l : list α} h, nth_le l (index_of a l) h = a
id                                    └──────────┘                  └──┘     └────┘   └──────┘      
src                                   └──────────┘                     └──┘       └────┘    └──────┘        
typ                                   └──────────┘                  └──┘     └────┘   └──────┘      
doc    └──┘
890  | (b::l) h := by by_cases h' : a = b; simp only [h', if_pos, if_false, index_of_cons, nth_le, @index_of_nth_le l]
id       └┘                                        └┘  └────┘  └──────┘  └───────────┘  └────┘   └─────────────┘ 
src      └┘           └───────┘  └─┘    └─────────┘  └┘└────┘└┘└──────┘└┘└───────────┘└┘└────┘└┘                 └─
typ      └┘           └───────┘  └─┘  └─────────┘└┘└┘└────┘└┘└──────┘└┘└───────────┘└┘└────┘└┘ └─────────────┘└─
doc                   └───────┘  └─┘     └─────────┘  └┘      └┘        └┘             └┘      └┘                 └─
txt                   └───────┘  └─┘     └─────────┘  └┘      └┘        └┘             └┘      └┘                 └─
par                   └───────┘  └─┘     └─────────┘  └┘      └┘        └┘             └┘      └┘                 └─
pid                             └─┘         └──┘└┘  └┘      └┘        └┘             └┘      └┘                 
st                   └─────────────────────────────────────────────────────────────────────────────────────────────────
891  
src  
typ  
doc  
txt  
par  
pid  
st   
892  @[simp] theorem index_of_nth [decidable_eq α] {a : α} {l : list α} (h : a ∈ l) : nth l (index_of a l) = some a :=
id                                 └──────────┘               └──┘              └─┘   └──────┘     └──┘ 
src                                └──────────┘                 └──┘                 └─┘    └──────┘       └──┘
typ                                └──────────┘               └──┘              └─┘   └──────┘     └──┘ 
doc    └──┘
893  by rw [nth_le_nth, index_of_nth_le (index_of_lt_length.2 h)]
id          └────────┘  └─────────────┘  └────────────────┘   
src     └──┘└────────┘└┘└─────────────┘ └────────────────┘└─┘ └──
typ     └──┘└────────┘└┘└─────────────┘ └────────────────┘└─┘└──
doc     └──┘          └┘                                  └─┘ └──
txt     └──┘          └┘                                  └─┘ └──
par     └──┘          └┘                                  └─┘ └──
pid       └┘          └┘                                  └─┘ └┘
st     └─────────────┘└────────────────────────────────────────┘
894  
src  
typ  
doc  
txt  
par  
pid  
st   
895  theorem nth_le_reverse_aux1 : ∀ (l r : list α) (i h1 h2), nth_le (reverse_core l r) (i + length l) h1 = nth_le r i h2
id                                         └──┘     └┘ └┘   └────┘  └──────────┘       └────┘   └┘  └────┘   └┘
src                                         └──┘               └────┘  └──────────┘          └────┘        └────┘
typ                                        └──┘     └┘ └┘   └────┘  └──────────┘       └────┘   └┘  └────┘   └┘
896  | []       r i := λh1 h2, rfl
id     └┘               └┘ └┘  └─┘
src    └┘                      └─┘
typ    └┘               └┘ └┘  └─┘
897  | (a :: l) r i := by rw (show i + length (a :: l) = i + 1 + length l, from add_right_comm i (length l) 1); exact
id        └┘                                                                 └────────────┘   └────┘ 
src       └┘              └─┘                 └┘  └─┘        └─────┘└────────────┘  └────┘ └──┘  └─────
typ       └┘              └─┘                └┘  └─┘        └─────┘└────────────┘ └────┘└──┘  └─────
doc                       └─┘                  └┘   └─┘        └─────┘                       └──┘  └─────
txt                       └─┘                  └┘   └─┘        └─────┘                       └──┘  └─────
par                       └─┘                  └┘   └─┘        └─────┘                       └──┘  └─────
pid                                           └┘   └─┘        └─────┘                       └──┘       
st                       └────────────────────────────────────────────────────────────────────────────────────────────
898    λh1 h2, nth_le_reverse_aux1 l (a :: r) (i+1) h1 (succ_lt_succ h2)
id             └─────────────────┘                  └──────────┘
src  ─┘ └─────┘                         └┘   └─┘   └──────────┘  └─
typ  ─┘ └─────┘└─────────────────┘   └┘  └─┘   └──────────┘  └─
doc  ─┘ └─────┘                         └┘   └─┘                 └─
txt  ─┘ └─────┘                         └┘   └─┘                 └─
par  ─┘ └─────┘                         └┘   └─┘                 └─
pid  ─┘ └─────┘                         └┘   └─┘                 
st   ────────────────────────────────────────────────────────────────────
899  
src  
typ  
doc  
txt  
par  
pid  
st   
900  lemma index_of_inj [decidable_eq α] {l : list α} {x y : α}
id                       └──────────┘        └──┘          
src                      └──────────┘         └──┘
typ                      └──────────┘        └──┘          
901    (hx : x ∈ l) (hy : y ∈ l) : index_of x l = index_of y l ↔ x = y :=
id                           └──────┘    └──────┘      
src                              └──────┘      └──────┘        
typ                          └──────┘    └──────┘      
902  ⟨λ h, have nth_le l (index_of x l) (index_of_lt_length.2 hx) =
id             └────┘   └──────┘     └────────────────┘  └┘  
src             └────┘    └──────┘       └────────────────┘      
typ            └────┘   └──────┘     └────────────────┘  └┘  
903          nth_le l (index_of y l) (index_of_lt_length.2 hy),
id           └────┘   └──────┘     └────────────────┘  └┘
src          └────┘    └──────┘       └────────────────┘
typ          └────┘   └──────┘     └────────────────┘  └┘
904        by simp only [h],
id                       
src           └─────────┘ 
typ           └─────────┘
doc           └─────────┘ 
txt           └─────────┘ 
par           └─────────┘ 
pid               └──┘└┘ 
st           └────────────┘
905      by simpa only [index_of_nth_le],
id                      └─────────────┘
src         └──────────┘└─────────────┘
typ         └──────────┘└─────────────┘
doc         └──────────┘               
txt         └──────────┘               
par         └──────────┘               
pid              └──┘└┘               
st         └───────────────────────────┘
906    λ h, by subst h⟩
id                  
src            └────┘
typ           └────┘
doc            └────┘
txt            └────┘
par            └────┘
pid                 
st            └──────┘
907  
908  theorem nth_le_reverse_aux2 : ∀ (l r : list α) (i : nat) (h1) (h2),
id                                         └──┘        └─┘   └┘   └┘
src                                         └──┘         └─┘
typ                                        └──┘        └─┘   └┘   └┘
909    nth_le (reverse_core l r) (length l - 1 - i) h1 = nth_le l i h2
id     └────┘  └──────────┘     └────┘        └┘  └────┘   └┘
src    └────┘  └──────────┘       └────┘              └────┘
typ    └────┘  └──────────┘     └────┘        └┘  └────┘   └┘
910  | []       r i     h1 h2 := absurd h2 (not_lt_zero _)
id     └┘                  └┘    └────┘     └─────────┘
src    └┘                        └────┘     └─────────┘
typ    └┘                  └┘    └────┘     └─────────┘
911  | (a :: l) r 0     h1 h2 := begin
id        └┘
src       └┘
typ       └┘
st                               └─────
912      have aux := nth_le_reverse_aux1 l (a :: r) 0,
id                   └─────────────────┘       
src      └──────────┘└─────────────────┘      └─┘
typ      └──────────┘└─────────────────┘   └─┘
doc      └──────────┘                         └─┘
txt      └──────────┘                         └─┘
par      └──────────┘                         └─┘
pid      └──────┘└─┘                         └┘
st   ───────────────────────────────────────────────┘└─
913      rw zero_add at aux,
id          └──────┘
src      └─┘└──────┘└─────┘
typ      └─┘└──────┘└─────┘
doc      └─┘        └─────┘
txt      └─┘        └─────┘
par      └─┘        └─────┘
pid                └─────┘
st   ─────────────────────┘└─
914      exact aux _ (zero_lt_succ _)
id             └─┘    └──────────┘
src      └────┘   └─┘ └──────────┘└───
typ      └────┘└─┘└─┘ └──────────┘└───
doc      └────┘   └─┘             └───
txt      └────┘   └─┘             └───
par      └────┘   └─┘             └───
pid              └─┘             └─┘
st   ─────────────────────────────────
915    end
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
916  | (a :: l) r (i+1) h1 h2 := begin
id        └┘        
src       └┘        
typ       └┘        
st                               └─────
917      have aux := nth_le_reverse_aux2 l (a :: r) i,
id                   └─────────────────┘         
src      └──────────┘                         └┘
typ      └──────────┘└─────────────────┘   └┘
doc      └──────────┘                         └┘
txt      └──────────┘                         └┘
par      └──────────┘                         └┘
pid      └──────┘└─┘                         └┘
st   ───────────────────────────────────────────────┘└─
918      have heq := calc length (a :: l) - 1 - (i + 1)
id                                               
src      └──────────┘               └┘└─┘   └───
typ      └──────────┘              └┘└─┘   └───
doc      └──────────┘               └┘ └─┘    └───
txt      └──────────┘               └┘ └─┘    └───
par      └──────────┘               └┘ └─┘    └───
pid      └──────┘└─┘               └┘ └─┘    └───
st   ───────────────────────────────────────────────────
919            = length l - (1 + i) : by rw add_comm; refl
id                                          └──────┘
src  ─────────┘          └┘  └──┘  └─┘└──────┘└┘└────
typ  ─────────┘          └┘  └──┘  └─┘└──────┘└┘└────
doc  ─────────┘          └┘  └──┘  └─┘        └┘└────
txt  ─────────┘          └┘  └──┘  └─┘        └┘└────
par  ─────────┘          └┘  └──┘  └─┘        └┘└────
pid  ─────────┘          └┘  └──┘  └──┘        └──────
st   ──────────────────────────────────┘└──────────────────
920        ... = length l - 1 - i   : by rw nat.sub_sub,
id               └────┘                   └─────────┘
src  ─────┘└──┘ └────┘  └─┘  └───┘  └─┘└─────────┘
typ  ─────┘└──┘ └────┘ └─┘ └───┘  └─┘└─────────┘
doc  ─────┘└──┘         └─┘  └───┘  └─┘
txt  ─────┘└──┘         └─┘  └───┘  └─┘
par  ─────┘└──┘         └─┘  └───┘  └─┘
pid  ─────────┘         └─┘  └───┘  └──┘
st   ─────┘└───────────────────────────┘└─────────────┘└─
921      rw [← heq] at aux,
id             └─┘
src      └────┘└─┘└──────┘
typ      └────┘└─┘└──────┘
doc      └────┘   └──────┘
txt      └────┘   └──────┘
par      └────┘   └──────┘
pid        └──┘   └─────┘
st   ────────────┘└─────┘└─
922      apply aux
src      └────┘   
typ      └────┘   
doc      └────┘   
txt      └────┘   
par      └────┘   
pid              
st   ──────────────
923    end
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
924  
925  @[simp] theorem nth_le_reverse (l : list α) (i : nat) (h1 h2) :
id                                       └──┘        └─┘
src                                      └──┘         └─┘
typ                                      └──┘        └─┘
doc    └──┘
926    nth_le (reverse l) (length l - 1 - i) h1 = nth_le l i h2 :=
id     └────┘  └─────┘    └────┘        └┘  └────┘   └┘
src    └────┘  └─────┘     └────┘              └────┘
typ    └────┘  └─────┘    └────┘        └┘  └────┘   └┘
927  nth_le_reverse_aux2 _ _ _ _ _
id   └─────────────────┘
src  └─────────────────┘
typ  └─────────────────┘
928  
929  lemma modify_nth_tail_modify_nth_tail {f g : list α → list α} (m : ℕ) :
id                                                └──┘    └──┘        
src                                               └──┘     └──┘         
typ                                               └──┘    └──┘        
930    ∀n (l:list α), (l.modify_nth_tail f n).modify_nth_tail g (m + n) =
id          └──┘     └──────────────┘   └─────────────┘        
src          └──┘       └──────────────┘     └─────────────┘           
typ         └──┘     └──────────────┘   └─────────────┘        
doc                     └──────────────┘     └─────────────┘
931      l.modify_nth_tail (λl, (f l).modify_nth_tail g m) n
id       └──────────────┘        └─────────────┘     
src       └──────────────┘           └─────────────┘
typ      └──────────────┘        └─────────────┘     
doc       └──────────────┘           └─────────────┘
932  | 0     l      := rfl
id                     └─┘
src                    └─┘
typ                    └─┘
933  | (n+1) []     := rfl
id          └┘        └─┘
src         └┘        └─┘
typ         └┘        └─┘
934  | (n+1) (a::l) := congr_arg (list.cons a) (modify_nth_tail_modify_nth_tail n l)
id          └┘     └───────┘  └───────┘     └─────────────────────────────┘
src           └┘      └───────┘  └───────┘
typ         └┘     └───────┘  └───────┘     └─────────────────────────────┘
935  
936  lemma modify_nth_tail_modify_nth_tail_le
937    {f g : list α → list α} (m n : ℕ) (l : list α) (h : n ≤ m) :
id            └──┘    └──┘                 └──┘          
src           └──┘     └──┘                  └──┘           
typ           └──┘    └──┘                 └──┘          
938    (l.modify_nth_tail f n).modify_nth_tail g m =
id      └──────────────┘   └─────────────┘    
src      └──────────────┘     └─────────────┘      
typ     └──────────────┘   └─────────────┘    
doc      └──────────────┘     └─────────────┘
939      l.modify_nth_tail (λl, (f l).modify_nth_tail g (m - n)) n :=
id       └──────────────┘        └─────────────┘         
src       └──────────────┘           └─────────────┘       
typ      └──────────────┘        └─────────────┘         
doc       └──────────────┘           └─────────────┘
940  begin
st   └─────
941    rcases le_iff_exists_add.1 h with ⟨m, rfl⟩,
id            └───────────────┘   
src    └─────┘└───────────────┘└─┘ └────────────┘
typ    └─────┘└───────────────┘└─┘└────────────┘
doc    └─────┘                 └─┘ └────────────┘
txt    └─────┘                 └─┘ └────────────┘
par    └─────┘                 └─┘ └────────────┘
pid                           └─┘ └────────────┘
st   ───────────────────────────────────────────┘└─
942    rw [nat.add_sub_cancel_left, add_comm, modify_nth_tail_modify_nth_tail]
id         └─────────────────────┘  └──────┘  └─────────────────────────────┘
src    └──┘└─────────────────────┘└┘└──────┘└┘└─────────────────────────────┘└┘
typ    └──┘└─────────────────────┘└┘└──────┘└┘└─────────────────────────────┘└┘
doc    └──┘                       └┘        └┘                               └┘
txt    └──┘                       └┘        └┘                               └┘
par    └──┘                       └┘        └┘                               └┘
pid      └┘                       └┘        └┘                               
st   ────────────────────────────┘└────────┘└───────────────────────────────┘
943  end
st   └─┘
944  
945  lemma modify_nth_tail_modify_nth_tail_same {f g : list α → list α} (n : ℕ) (l:list α) :
id                                                     └──┘    └──┘             └──┘ 
src                                                    └──┘     └──┘              └──┘
typ                                                    └──┘    └──┘             └──┘ 
946    (l.modify_nth_tail f n).modify_nth_tail g n = l.modify_nth_tail (g ∘ f) n :=
id      └──────────────┘   └─────────────┘     └──────────────┘      
src      └──────────────┘     └─────────────┘        └──────────────┘    
typ     └──────────────┘   └─────────────┘     └──────────────┘      
doc      └──────────────┘     └─────────────┘         └──────────────┘
947  by rw [modify_nth_tail_modify_nth_tail_le n n l (le_refl n), nat.sub_self]; refl
id          └────────────────────────────────┘       └─────┘    └──────────┘
src     └──┘└────────────────────────────────┘    └─────┘ └─┘└──────────┘  └────
typ     └──┘└────────────────────────────────┘   └─────┘└─┘└──────────┘  └────
doc     └──┘                                              └─┘              └────
txt     └──┘                                              └─┘              └────
par     └──┘                                              └─┘              └────
pid       └┘                                              └─┘                  
st     └───────────────────────────────────────────────────────┘└────────────┘└──────
948  
src  
typ  
doc  
txt  
par  
pid  
st   
949  lemma modify_nth_tail_id :
950    ∀n (l:list α), l.modify_nth_tail id n = l
id          └──┘    └──────────────┘ └┘   
src          └──┘      └──────────────┘ └┘   
typ         └──┘    └──────────────┘ └┘   
doc                    └──────────────┘
951  | 0     l      := rfl
id                     └─┘
src                    └─┘
typ                    └─┘
952  | (n+1) []     := rfl
id          └┘        └─┘
src         └┘        └─┘
typ         └┘        └─┘
953  | (n+1) (a::l) := congr_arg (list.cons a) (modify_nth_tail_id n l)
id          └┘     └───────┘  └───────┘     └────────────────┘
src           └┘      └───────┘  └───────┘
typ         └┘     └───────┘  └───────┘     └────────────────┘
954  
955  theorem remove_nth_eq_nth_tail : ∀ n (l : list α), remove_nth l n = modify_nth_tail tail n l
id                                            └──┘    └────────┘    └─────────────┘ └──┘  
src                                            └──┘     └────────┘      └─────────────┘ └──┘
typ                                           └──┘    └────────┘    └─────────────┘ └──┘  
doc                                                                      └─────────────┘
956  | 0     l      := by cases l; refl
id                              
src                       └────┘   └───┘
typ                       └────┘  └───┘
doc                       └────┘   └───┘
txt                       └────┘   └───┘
par                       └────┘   └───┘
pid                                   
st                       └─────────────┘
957  | (n+1) []     := rfl
id          └┘        └─┘
src         └┘        └─┘
typ         └┘        └─┘
958  | (n+1) (a::l) := congr_arg (cons _) (remove_nth_eq_nth_tail _ _)
id            └┘      └───────┘  └──┘     └────────────────────┘
src           └┘      └───────┘  └──┘
typ           └┘      └───────┘  └──┘     └────────────────────┘
959  
960  theorem update_nth_eq_modify_nth (a : α) : ∀ n (l : list α),
id                                                     └──┘ 
src                                                      └──┘
typ                                                    └──┘ 
961    update_nth l n a = modify_nth (λ _, a) n l
id     └────────┘     └────────┘         
src    └────────┘        └────────┘
typ    └────────┘     └────────┘         
doc                       └────────┘
962  | 0     l      := by cases l; refl
id                              
src                       └────┘   └───┘
typ                       └────┘  └───┘
doc                       └────┘   └───┘
txt                       └────┘   └───┘
par                       └────┘   └───┘
pid                                   
st                       └─────────────┘
963  | (n+1) []     := rfl
id          └┘        └─┘
src         └┘        └─┘
typ         └┘        └─┘
964  | (n+1) (b::l) := congr_arg (cons _) (update_nth_eq_modify_nth _ _)
id            └┘      └───────┘  └──┘     └──────────────────────┘
src           └┘      └───────┘  └──┘
typ           └┘      └───────┘  └──┘     └──────────────────────┘
965  
966  theorem modify_nth_eq_update_nth (f : α → α) : ∀ n (l : list α),
id                                                        └──┘ 
src                                                          └──┘
typ                                                       └──┘ 
967    modify_nth f n l = ((λ a, update_nth l n (f a)) <$> nth l n).get_or_else l
id     └────────┘           └────────┘        └─┘ └─┘   └─────────┘  
src    └────────┘               └────────┘            └─┘ └─┘     └─────────┘
typ    └────────┘           └────────┘        └─┘ └─┘   └─────────┘  
doc    └────────┘
968  | 0     l      := by cases l; refl
id                              
src                       └────┘   └───┘
typ                       └────┘  └───┘
doc                       └────┘   └───┘
txt                       └────┘   └───┘
par                       └────┘   └───┘
pid                                   
st                       └─────────────┘
969  | (n+1) []     := rfl
id          └┘        └─┘
src         └┘        └─┘
typ         └┘        └─┘
970  | (n+1) (b::l) := (congr_arg (cons b)
id          └┘      └───────┘  └──┘
src           └┘       └───────┘  └──┘
typ         └┘      └───────┘  └──┘
971    (modify_nth_eq_update_nth n l)).trans $ by cases nth l n; refl
id      └──────────────────────┘      └───┘             └─┘  
src                                   └───┘       └────┘└─┘    └────
typ     └──────────────────────┘      └───┘       └────┘└─┘  └────
doc                                               └────┘       └────
txt                                               └────┘       └────
par                                               └────┘       └────
pid                                                               
st                                               └────────────────────
972  
src  
typ  
doc  
txt  
par  
pid  
st   
973  theorem nth_modify_nth (f : α → α) : ∀ n (l : list α) m,
id                                              └──┘   
src                                                └──┘
typ                                             └──┘   
974    nth (modify_nth f n l) m = (λ a, if n = m then f a else a) <$> nth l m
id     └─┘  └────────┘                                └─┘ └─┘  
src    └─┘  └────────┘                                          └─┘ └─┘
typ    └─┘  └────────┘                                └─┘ └─┘  
doc         └────────┘
975  | n     l      0     := by cases l; cases n; refl
id                                            
src                             └────┘   └────┘   └───┘
typ                             └────┘  └────┘  └───┘
doc                             └────┘   └────┘   └───┘
txt                             └────┘   └────┘   └───┘
par                             └────┘   └────┘   └───┘
pid                                                 
st                             └──────────────────────┘
976  | n     []     (m+1) := by cases n; refl
id           └┘                      
src          └┘                └────┘   └───┘
typ          └┘                └────┘  └───┘
doc                             └────┘   └───┘
txt                             └────┘   └───┘
par                             └────┘   └───┘
pid                                         
st                             └─────────────┘
977  | 0     (a::l) (m+1) := by cases nth l m; refl
id             └┘                    └─┘  
src            └┘              └────┘└─┘    └───┘
typ            └┘              └────┘└─┘  └───┘
doc                             └────┘       └───┘
txt                             └────┘       └───┘
par                             └────┘       └───┘
pid                                             
st                             └───────────────────┘
978  | (n+1) (a::l) (m+1) := (nth_modify_nth n l m).trans $
id           └┘          └────────────┘       └───┘
src           └┘                                 └───┘
typ          └┘          └────────────┘       └───┘
979    by cases nth l m with b; by_cases n = m;
id              └─┘                      
src       └────┘└─┘  └─────┘  └───────┘ 
typ       └────┘└─┘└─────┘  └───────┘
doc       └────┘     └─────┘  └───────┘  
txt       └────┘     └─────┘  └───────┘  
par       └────┘     └─────┘  └───────┘  
pid                 └─────┘            
st       └──────────────────────────────────────
980    simp only [h, if_pos, if_true, if_false, option.map_none, option.map_some, mt succ_inj, not_false_iff]
id                  └────┘  └─────┘  └──────┘  └─────────────┘  └─────────────┘  └┘ └──────┘  └───────────┘
src    └─────────┘ └┘└────┘└┘└─────┘└┘└──────┘└┘└─────────────┘└┘└─────────────┘└┘└┘└──────┘└┘└───────────┘└─
typ    └─────────┘└┘└────┘└┘└─────┘└┘└──────┘└┘└─────────────┘└┘└─────────────┘└┘└┘└──────┘└┘└───────────┘└─
doc    └─────────┘ └┘      └┘       └┘        └┘               └┘               └┘          └┘             └─
txt    └─────────┘ └┘      └┘       └┘        └┘               └┘               └┘          └┘             └─
par    └─────────┘ └┘      └┘       └┘        └┘               └┘               └┘          └┘             └─
pid        └──┘└┘ └┘      └┘       └┘        └┘               └┘               └┘          └┘             
st   ─────────────────────────────────────────────────────────────────────────────────────────────────────────
981  
src  
typ  
doc  
txt  
par  
pid  
st   
982  theorem modify_nth_tail_length (f : list α → list α) (H : ∀ l, length (f l) = length l) :
id                                       └──┘    └──┘            └────┘      └────┘ 
src                                      └──┘     └──┘              └────┘        └────┘
typ                                      └──┘    └──┘            └────┘      └────┘ 
983    ∀ n l, length (modify_nth_tail f n l) = length l
id          └────┘  └─────────────┘      └────┘ 
src           └────┘  └─────────────┘         └────┘
typ         └────┘  └─────────────┘      └────┘ 
doc                   └─────────────┘
984  | 0     l      := H _
id                     
typ                    
985  | (n+1) []     := rfl
id          └┘        └─┘
src         └┘        └─┘
typ         └┘        └─┘
986  | (n+1) (a::l) := @congr_arg _ _ _ _ (+1) (modify_nth_tail_length _ _)
id            └┘       └───────┘              └────────────────────┘
src           └┘       └───────┘         
typ           └┘       └───────┘              └────────────────────┘
987  
988  @[simp] theorem modify_nth_length (f : α → α) :
id                                             
typ                                            
doc    └──┘
989    ∀ n l, length (modify_nth f n l) = length l :=
id          └────┘  └────────┘      └────┘ 
src           └────┘  └────────┘         └────┘
typ         └────┘  └────────┘      └────┘ 
doc                   └────────┘
990  modify_nth_tail_length _ (λ l, by cases l; refl)
id   └────────────────────┘                 
src  └────────────────────┘            └────┘   └──┘
typ  └────────────────────┘           └────┘  └──┘
doc                                    └────┘   └──┘
txt                                    └────┘   └──┘
par                                    └────┘   └──┘
pid                                         
st                                    └────────────┘
991  
992  @[simp] theorem update_nth_length (l : list α) (n) (a : α) :
id                                          └──┘            
src                                         └──┘
typ                                         └──┘            
doc    └──┘
993    length (update_nth l n a) = length l :=
id     └────┘  └────────┘      └────┘ 
src    └────┘  └────────┘         └────┘
typ    └────┘  └────────┘      └────┘ 
994  by simp only [update_nth_eq_modify_nth, modify_nth_length]
id                 └──────────────────────┘  └───────────────┘
src     └─────────┘└──────────────────────┘└┘└───────────────┘└─
typ     └─────────┘└──────────────────────┘└┘└───────────────┘└─
doc     └─────────┘                        └┘                 └─
txt     └─────────┘                        └┘                 └─
par     └─────────┘                        └┘                 └─
pid         └──┘└┘                        └┘                 
st     └────────────────────────────────────────────────────────
995  
src  
typ  
doc  
txt  
par  
pid  
st   
996  @[simp] theorem nth_modify_nth_eq (f : α → α) (n) (l : list α) :
id                                                        └──┘ 
src                                                         └──┘
typ                                                       └──┘ 
doc    └──┘
997    nth (modify_nth f n l) n = f <$> nth l n :=
id     └─┘  └────────┘        └─┘ └─┘  
src    └─┘  └────────┘             └─┘ └─┘
typ    └─┘  └────────┘        └─┘ └─┘  
doc         └────────┘
998  by simp only [nth_modify_nth, if_pos]
id                 └────────────┘  └────┘
src     └─────────┘└────────────┘└┘└────┘└─
typ     └─────────┘└────────────┘└┘└────┘└─
doc     └─────────┘              └┘      └─
txt     └─────────┘              └┘      └─
par     └─────────┘              └┘      └─
pid         └──┘└┘              └┘      
st     └───────────────────────────────────
999  
src  
typ  
doc  
txt  
par  
pid  
st   
1000  @[simp] theorem nth_modify_nth_ne (f : α → α) {m n} (l : list α) (h : m ≠ n) :
id                                                          └──┘          
src                                                           └──┘           
typ                                                         └──┘          
doc    └──┘
1001    nth (modify_nth f m l) n = nth l n :=
id     └─┘  └────────┘       └─┘  
src    └─┘  └────────┘           └─┘
typ    └─┘  └────────┘       └─┘  
doc         └────────┘
1002  by simp only [nth_modify_nth, if_neg h, id_map']
id                 └────────────┘  └────┘   └─────┘
src     └─────────┘└────────────┘└┘└────┘ └┘└─────┘└─
typ     └─────────┘└────────────┘└┘└────┘└┘└─────┘└─
doc     └─────────┘              └┘       └┘       └─
txt     └─────────┘              └┘       └┘       └─
par     └─────────┘              └┘       └┘       └─
pid         └──┘└┘              └┘       └┘       
st     └──────────────────────────────────────────────
1003  
src  
typ  
doc  
txt  
par  
pid  
st   
1004  theorem nth_update_nth_eq (a : α) (n) (l : list α) :
id                                             └──┘ 
src                                             └──┘
typ                                            └──┘ 
1005    nth (update_nth l n a) n = (λ _, a) <$> nth l n :=
id     └─┘  └────────┘              └─┘ └─┘  
src    └─┘  └────────┘                    └─┘ └─┘
typ    └─┘  └────────┘              └─┘ └─┘  
1006  by simp only [update_nth_eq_modify_nth, nth_modify_nth_eq]
id                 └──────────────────────┘  └───────────────┘
src     └─────────┘└──────────────────────┘└┘└───────────────┘└─
typ     └─────────┘└──────────────────────┘└┘└───────────────┘└─
doc     └─────────┘                        └┘                 └─
txt     └─────────┘                        └┘                 └─
par     └─────────┘                        └┘                 └─
pid         └──┘└┘                        └┘                 
st     └────────────────────────────────────────────────────────
1007  
src  
typ  
doc  
txt  
par  
pid  
st   
1008  theorem nth_update_nth_of_lt (a : α) {n} {l : list α} (h : n < length l) :
id                                                └──┘          └────┘ 
src                                                └──┘            └────┘
typ                                               └──┘          └────┘ 
1009    nth (update_nth l n a) n = some a :=
id     └─┘  └────────┘       └──┘ 
src    └─┘  └────────┘           └──┘
typ    └─┘  └────────┘       └──┘ 
1010  by rw [nth_update_nth_eq, nth_le_nth h]; refl
id          └───────────────┘  └────────┘ 
src     └──┘└───────────────┘└┘└────────┘   └────
typ     └──┘└───────────────┘└┘└────────┘  └────
doc     └──┘                 └┘             └────
txt     └──┘                 └┘             └────
par     └──┘                 └┘             └────
pid       └┘                 └┘                 
st     └────────────────────┘└────────────┘└──────
1011  
src  
typ  
doc  
txt  
par  
pid  
st   
1012  theorem nth_update_nth_ne (a : α) {m n} (l : list α) (h : m ≠ n) :
id                                               └──┘          
src                                               └──┘           
typ                                              └──┘          
1013    nth (update_nth l m a) n = nth l n :=
id     └─┘  └────────┘       └─┘  
src    └─┘  └────────┘           └─┘
typ    └─┘  └────────┘       └─┘  
1014  by simp only [update_nth_eq_modify_nth, nth_modify_nth_ne _ _ h]
id                 └──────────────────────┘  └───────────────┘     
src     └─────────┘└──────────────────────┘└┘└───────────────┘└───┘ └─
typ     └─────────┘└──────────────────────┘└┘└───────────────┘└───┘└─
doc     └─────────┘                        └┘                 └───┘ └─
txt     └─────────┘                        └┘                 └───┘ └─
par     └─────────┘                        └┘                 └───┘ └─
pid         └──┘└┘                        └┘                 └───┘ 
st     └──────────────────────────────────────────────────────────────
1015  
src  
typ  
doc  
txt  
par  
pid  
st   
1016  @[simp] lemma nth_le_update_nth_eq (l : list α) (i : ℕ) (a : α)
id                                           └──┘               
src                                          └──┘         
typ                                          └──┘               
doc    └──┘
1017    (h : i < (l.update_nth i a).length) : (l.update_nth i a).nth_le i h = a :=
id             └─────────┘   └────┘      └─────────┘   └────┘     
src              └─────────┘     └────┘       └─────────┘     └────┘      
typ            └─────────┘   └────┘      └─────────┘   └────┘     
1018  by rw [← option.some_inj, ← nth_le_nth, nth_update_nth_eq, nth_le_nth]; simp * at *
id            └─────────────┘    └────────┘  └───────────────┘  └────────┘
src     └────┘└─────────────┘└──┘└────────┘└┘└───────────────┘└┘└────────┘  └───────────
typ     └────┘└─────────────┘└──┘└────────┘└┘└───────────────┘└┘└────────┘  └───────────
doc     └────┘               └──┘          └┘                 └┘            └───────────
txt     └────┘               └──┘          └┘                 └┘            └───────────
par     └────┘               └──┘          └┘                 └┘            └───────────
pid       └──┘               └──┘          └┘                 └┘                └──┘
st     └────────────────────┘└────────────┘└─────────────────┘└──────────┘└─────────────
1019  
src  
typ  
doc  
txt  
par  
pid  
st   
1020  @[simp] lemma nth_le_update_nth_of_ne {l : list α} {i j : ℕ} (h : i ≠ j) (a : α)
id                                              └──┘                          
src                                             └──┘                    
typ                                             └──┘                          
doc    └──┘
1021    (hj : j < (l.update_nth i a).length) :
id              └─────────┘   └────┘
src               └─────────┘     └────┘
typ             └─────────┘   └────┘
1022    (l.update_nth i a).nth_le j hj = l.nth_le j (by simpa using hj) :=
id      └─────────┘   └────┘   └┘  └─────┘                  └┘
src      └─────────┘     └────┘         └─────┘       └──────────┘
typ     └─────────┘   └────┘   └┘  └─────┘      └──────────┘└┘
doc                                                    └──────────┘
txt                                                    └──────────┘
par                                                    └──────────┘
pid                                                         └────┘
st                                                    └─────────────┘
1023  by rw [← option.some_inj, ← list.nth_le_nth, list.nth_update_nth_ne _ _ h, list.nth_le_nth]
id            └─────────────┘    └─────────────┘  └────────────────────┘       └─────────────┘
src     └────┘└─────────────┘└──┘└─────────────┘└┘└────────────────────┘└───┘ └┘└─────────────┘└─
typ     └────┘└─────────────┘└──┘└─────────────┘└┘└────────────────────┘└───┘└┘└─────────────┘└─
doc     └────┘               └──┘               └┘                      └───┘ └┘               └─
txt     └────┘               └──┘               └┘                      └───┘ └┘               └─
par     └────┘               └──┘               └┘                      └───┘ └┘               └─
pid       └──┘               └──┘               └┘                      └───┘ └┘               
st     └────────────────────┘└─────────────────┘└────────────────────────────┘└───────────────┘
1024  
src  
typ  
doc  
txt  
par  
pid  
st   
1025  lemma mem_or_eq_of_mem_update_nth : ∀ {l : list α} {n : ℕ} {a b : α}
id                                             └──┘                 
src                                             └──┘         
typ                                            └──┘                 
1026    (h : a ∈ l.update_nth n b), a ∈ l ∨ a = b
id            └─────────┘           
src             └─────────┘               
typ           └─────────┘           
1027  | []     n     a b h := false.elim h
id     └┘                   └────────┘
src    └┘                    └────────┘
typ    └┘                   └────────┘
1028  | (c::l) 0     a b h := ((mem_cons_iff _ _ _).1 h).elim
id       └┘                   └──────────┘           └──┘
src      └┘                    └──────────┘           └──┘
typ      └┘                   └──────────┘           └──┘
1029    or.inr (or.inl ∘ mem_cons_of_mem _)
id     └────┘  └────┘  └─────────────┘
src    └────┘  └────┘  └─────────────┘
typ    └────┘  └────┘  └─────────────┘
1030  | (c::l) (n+1) a b h := ((mem_cons_iff _ _ _).1 h).elim
id       └┘                  └──────────┘           └──┘
src      └┘                   └──────────┘           └──┘
typ      └┘                  └──────────┘           └──┘
1031    (λ h, h ▸ or.inl (mem_cons_self _ _))
id            └────┘  └───────────┘
src             └────┘  └───────────┘
typ           └────┘  └───────────┘
1032    (λ h, (mem_or_eq_of_mem_update_nth h).elim
id           └─────────────────────────┘  └──┘
src                                         └──┘
typ          └─────────────────────────┘  └──┘
1033      (or.inl ∘ mem_cons_of_mem _) or.inr)
id        └────┘  └─────────────┘    └────┘
src       └────┘  └─────────────┘    └────┘
typ       └────┘  └─────────────┘    └────┘
1034  
1035  section insert_nth
1036  variable {a : α}
1037  
1038  @[simp] lemma insert_nth_nil (a : α) : insert_nth 0 a [] = [a] := rfl
id                                         └────────┘    └┘      └─┘
src                                         └────────┘     └┘       └─┘
typ                                        └────────┘    └┘      └─┘
doc    └──┘
1039  
1040  lemma length_insert_nth : ∀n as, n ≤ length as → length (insert_nth n a as) = length as + 1
id                               └┘    └────┘ └┘   └────┘  └────────┘   └┘   └────┘ └┘ 
src                                      └────┘      └────┘  └────────┘          └────┘    
typ                              └┘    └────┘ └┘   └────┘  └────────┘   └┘   └────┘ └┘ 
1041  | 0     as       h := rfl
id                         └─┘
src                        └─┘
typ                        └─┘
1042  | (n+1) []       h := (nat.not_succ_le_zero _ h).elim
id          └┘            └──────────────────┘     └──┘
src         └┘             └──────────────────┘     └──┘
typ         └┘            └──────────────────┘     └──┘
1043  | (n+1) (a'::as) h := congr_arg nat.succ $ length_insert_nth n as (nat.le_of_succ_le_succ h)
id            └┘└┘      └───────┘ └──────┘   └───────────────┘       └────────────────────┘
src            └┘         └───────┘ └──────┘                           └────────────────────┘
typ           └┘└┘      └───────┘ └──────┘   └───────────────┘       └────────────────────┘
1044  
1045  lemma remove_nth_insert_nth (n:ℕ) (l : list α) : (l.insert_nth n a).remove_nth n = l :=
id                                         └──┘      └─────────┘   └────────┘    
src                                        └──┘        └─────────┘     └────────┘    
typ                                        └──┘      └─────────┘   └────────┘    
1046  by rw [remove_nth_eq_nth_tail, insert_nth, modify_nth_tail_modify_nth_tail_same];
id          └────────────────────┘  └────────┘  └──────────────────────────────────┘
src     └──┘└────────────────────┘└┘└────────┘└┘└──────────────────────────────────┘
typ     └──┘└────────────────────┘└┘└────────┘└┘└──────────────────────────────────┘
doc     └──┘                      └┘          └┘                                    
txt     └──┘                      └┘          └┘                                    
par     └──┘                      └┘          └┘                                    
pid       └┘                      └┘          └┘                                    
st     └─────────────────────────┘└──────────┘└────────────────────────────────────┘└─
1047  from modify_nth_tail_id _ _
id        └────────────────┘
src  └───┘└────────────────┘└────
typ  └───┘└────────────────┘└────
doc  └───┘                  └────
txt  └───┘                  └────
par  └───┘                  └────
pid  └───┘                  └──┘
st   ────────────────────────────
1048  
src  
typ  
doc  
txt  
par  
pid  
st   
1049  lemma insert_nth_remove_nth_of_ge : ∀n m as, n < length as → m ≥ n →
id                                          └┘    └────┘ └┘     
src                                                  └────┘        
typ                                         └┘    └────┘ └┘     
1050    insert_nth m a (as.remove_nth n) = (as.insert_nth (m + 1) a).remove_nth n
id     └────────┘    └┘└─────────┘     └┘└─────────┘        └────────┘  
src    └────────┘        └─────────┘        └─────────┘          └────────┘
typ    └────────┘    └┘└─────────┘     └┘└─────────┘        └────────┘  
1051  | 0     0     []      has _   := (lt_irrefl _ has).elim
id                 └┘      └─┘         └───────┘       └──┘
src                └┘                  └───────┘       └──┘
typ                └┘      └─┘         └───────┘       └──┘
1052  | 0     0     (a::as) has hmn := by simp [remove_nth, insert_nth]
id                   └┘                        └────────┘  └────────┘
src                  └┘                  └────┘└────────┘└┘└────────┘└┘
typ                  └┘                  └────┘└────────┘└┘└────────┘└┘
doc                                      └────┘          └┘          └┘
txt                                      └────┘          └┘          └┘
par                                      └────┘          └┘          └┘
pid                                                    └┘          
st                                      └─────────────────────────────┘
1053  | 0     (m+1) (a::as) has hmn := rfl
id                  └┘               └─┘
src                 └┘               └─┘
typ                 └┘               └─┘
1054  | (n+1) (m+1) (a::as) has hmn :=
id              └┘└┘  └─┘ └─┘
src                └┘
typ             └┘└┘  └─┘ └─┘
1055    congr_arg (cons a) $
id     └───────┘  └──┘
src    └───────┘  └──┘
typ    └───────┘  └──┘
1056      insert_nth_remove_nth_of_ge n m as (nat.lt_of_succ_lt_succ has) (nat.le_of_succ_le_succ hmn)
id       └─────────────────────────┘         └────────────────────┘       └────────────────────┘
src                                          └────────────────────┘       └────────────────────┘
typ      └─────────────────────────┘         └────────────────────┘       └────────────────────┘
1057  
1058  lemma insert_nth_remove_nth_of_le : ∀n m as, n < length as → m ≤ n →
id                                          └┘    └────┘ └┘     
src                                                  └────┘        
typ                                         └┘    └────┘ └┘     
1059    insert_nth m a (as.remove_nth n) = (as.insert_nth m a).remove_nth (n + 1)
id     └────────┘    └┘└─────────┘     └┘└─────────┘   └────────┘    
src    └────────┘        └─────────┘        └─────────┘     └────────┘     
typ    └────────┘    └┘└─────────┘     └┘└─────────┘   └────────┘    
1060  | n       0       (a :: as) has hmn := rfl
id                        └┘                └─┘
src                       └┘                └─┘
typ                       └┘                └─┘
1061  | (n + 1) (m + 1) (a :: as) has hmn :=
id                   └┘ └┘  └─┘ └─┘
src                     └┘
typ                  └┘ └┘  └─┘ └─┘
1062    congr_arg (cons a) $
id     └───────┘  └──┘
src    └───────┘  └──┘
typ    └───────┘  └──┘
1063      insert_nth_remove_nth_of_le n m as (nat.lt_of_succ_lt_succ has) (nat.le_of_succ_le_succ hmn)
id       └─────────────────────────┘         └────────────────────┘       └────────────────────┘
src                                          └────────────────────┘       └────────────────────┘
typ      └─────────────────────────┘         └────────────────────┘       └────────────────────┘
1064  
1065  lemma insert_nth_comm (a b : α) :
id                                
typ                               
1066    ∀(i j : ℕ) (l : list α) (h : i ≤ j) (hj : j ≤ length l),
id                   └──┘                    └────┘ 
src                   └──┘                        └────┘
typ                  └──┘                    └────┘ 
1067      (l.insert_nth i a).insert_nth (j + 1) b = (l.insert_nth j b).insert_nth i a
id        └─────────┘   └────────┘           └─────────┘   └────────┘   
src        └─────────┘     └────────┘              └─────────┘     └────────┘
typ       └─────────┘   └────────┘           └─────────┘   └────────┘   
1068  | 0       j     l      := by simp [insert_nth]
id                                      └────────┘
src                               └────┘└────────┘└┘
typ                               └────┘└────────┘└┘
doc                               └────┘          └┘
txt                               └────┘          └┘
par                               └────┘          └┘
pid                                             
st                               └─────────────────┘
1069  | (i + 1) 0     l      := assume h, (nat.not_lt_zero _ h).elim
id                                      └─────────────┘    └──┘
src                                      └─────────────┘     └──┘
typ                                     └─────────────┘    └──┘
1070  | (i + 1) (j+1) []     := by simp
id                 └┘
src                └┘           └───┘
typ                └┘           └───┘
doc                               └───┘
txt                               └───┘
par                               └───┘
pid                                   
st                               └────┘
1071  | (i + 1) (j+1) (c::l) :=
id                   └┘
src                  └┘
typ                  └┘
1072    assume h₀ h₁,
id            └┘ └┘
typ           └┘ └┘
1073    by simp [insert_nth]; exact insert_nth_comm i j l (nat.le_of_succ_le_succ h₀) (nat.le_of_succ_le_succ h₁)
id              └────────┘         └─────────────┘                            └┘   └────────────────────┘ └┘
src       └────┘└────────┘  └────┘                                           └┘ └────────────────────┘  └─
typ       └────┘└────────┘  └────┘└─────────────┘                       └┘└┘ └────────────────────┘└┘└─
doc       └────┘            └────┘                                           └┘                         └─
txt       └────┘            └────┘                                           └┘                         └─
par       └────┘            └────┘                                           └┘                         └─
pid                                                                       └┘                         
st       └───────────────────────────────────────────────────────────────────────────────────────────────────────
1074  
src  
typ  
doc  
txt  
par  
pid  
st   
1075  lemma mem_insert_nth {a b : α} : ∀ {n : ℕ} {l : list α} (hi : n ≤ l.length),
id                                                └──┘           └─────┘
src                                                 └──┘              └─────┘
typ                                               └──┘           └─────┘
1076    a ∈ l.insert_nth n b ↔ a = b ∨ a ∈ l
id       └─────────┘          
src        └─────────┘              
typ      └─────────┘          
1077  | 0     as       h := iff.rfl
id                         └─────┘
src                        └─────┘
typ                        └─────┘
1078  | (n+1) []       h := (nat.not_succ_le_zero _ h).elim
id          └┘            └──────────────────┘     └──┘
src         └┘             └──────────────────┘     └──┘
typ         └┘            └──────────────────┘     └──┘
1079  | (n+1) (a'::as) h := begin
id             └┘
src            └┘
typ            └┘
st                         └─────
1080    dsimp [list.insert_nth],
id            └─────────────┘
src    └─────┘└─────────────┘
typ    └─────┘└─────────────┘
doc    └─────┘               
txt    └─────┘               
par    └─────┘               
pid                        
st   ────────────────────────┘└─
1081    erw [list.mem_cons_iff, mem_insert_nth (nat.le_of_succ_le_succ h), list.mem_cons_iff,
id          └───────────────┘  └────────────┘  └────────────────────┘    └───────────────┘
src    └───┘└───────────────┘└┘               └────────────────────┘ └─┘└───────────────┘└─
typ    └───┘└───────────────┘└┘└────────────┘ └────────────────────┘└─┘└───────────────┘└─
doc    └───┘                 └┘                                      └─┘                 └─
txt    └───┘                 └┘                                      └─┘                 └─
par    └───┘                 └┘                                      └─┘                 └─
pid       └┘                 └┘                                      └─┘                 └─
st   ───────────────────────┘└─────────────────────────────────────────┘└─────────────────┘└─
1082      ← or.assoc, or_comm (a = a'), or.assoc]
id         └──────┘  └─────┘    └┘   └──────┘
src  ─────┘└──────┘└┘└─────┘    └─┘└──────┘└┘
typ  ─────┘└──────┘└┘└─────┘ └┘└─┘└──────┘└┘
doc  ─────┘        └┘            └─┘        └┘
txt  ─────┘        └┘            └─┘        └┘
par  ─────┘        └┘            └─┘        └┘
pid  ─────┘        └┘            └─┘        
st   ─────────────┘└────────────────┘└────────┘
1083  end
st   └─┘
1084  
1085  end insert_nth
1086  
1087  /- map -/
1088  
1089  lemma map_congr {f g : α → β} : ∀ {l : list α}, (∀ x ∈ l, f x = g x) → map f l = map g l
id                                       └──┘                    └─┘    └─┘  
src                                         └──┘                           └─┘      └─┘
typ                                      └──┘                    └─┘    └─┘  
1090  | []     _ := rfl
id     └┘          └─┘
src    └┘          └─┘
typ    └┘          └─┘
1091  | (a::l) h := let ⟨h₁, h₂⟩ := forall_mem_cons.1 h in
id       └┘       └─┘             └─────────────┘
src      └┘                        └─────────────┘
typ      └┘       └─┘             └─────────────┘
1092    by rw [map, map, h₁, map_congr h₂]
id            └─┘  └─┘  └┘  └───────┘ └┘
src       └──┘└─┘└┘└─┘└┘  └┘           └─
typ       └──┘└─┘└┘└─┘└┘└┘└┘└───────┘└┘└─
doc       └──┘   └┘   └┘  └┘           └─
txt       └──┘   └┘   └┘  └┘           └─
par       └──┘   └┘   └┘  └┘           └─
pid         └┘   └┘   └┘  └┘           
st       └──────┘└───┘└──┘└────────────┘
1093  
src  
typ  
doc  
txt  
par  
pid  
st   
1094  lemma map_eq_map_iff {f g : α → β} {l : list α} : map f l = map g l ↔ (∀ x ∈ l, f x = g x) :=
id                                         └──┘     └─┘    └─┘                
src                                          └──┘      └─┘      └─┘                    
typ                                        └──┘     └─┘    └─┘                
1095  begin
st   └─────
1096    refine ⟨_, map_congr⟩, intros h x hx,
id                └───────┘
src    └─────┘ └─┘└───────┘  └───────────┘
typ    └─────┘ └─┘└───────┘  └───────────┘
doc    └─────┘ └─┘           └───────────┘
txt    └─────┘ └─┘           └───────────┘
par    └─────┘ └─┘           └───────────┘
pid           └─┘                 └─────┘
st   ──────────────────────┘└─────────────┘└─
1097    rw [mem_iff_nth_le] at hx, rcases hx with ⟨n, hn, rfl⟩,
id         └────────────┘                └┘
src    └──┘└────────────┘└─────┘  └─────┘  └────────────────┘
typ    └──┘└────────────┘└─────┘  └─────┘└┘└────────────────┘
doc    └──┘              └─────┘  └─────┘  └────────────────┘
txt    └──┘              └─────┘  └─────┘  └────────────────┘
par    └──┘              └─────┘  └─────┘  └────────────────┘
pid      └┘              └────┘          └────────────────┘
st   ───────────────────┘└────┘└───────────────────────────┘└─
1098    rw [nth_le_map_rev f, nth_le_map_rev g], congr, exact h
id         └────────────┘   └────────────┘                 
src    └──┘└────────────┘ └┘└────────────┘   └───┘  └────┘ 
typ    └──┘└────────────┘└┘└────────────┘  └───┘  └────┘
doc    └──┘└────────────┘ └┘└────────────┘          └────┘ 
txt    └──┘               └┘                 └───┘  └────┘ 
par    └──┘               └┘                 └───┘  └────┘ 
pid      └┘               └┘                              
st   ─────────────────────┘└────────────────┘└──────┘└────────┘
1099  end
st   └─┘
1100  
1101  theorem map_concat (f : α → β) (a : α) (l : list α) : map f (concat l a) = concat (map f l) (f a) :=
id                                            └──┘     └─┘   └────┘     └────┘  └─┘      
src                                              └──┘      └─┘    └────┘       └────┘  └─┘
typ                                           └──┘     └─┘   └────┘     └────┘  └─┘      
doc                                                               └────┘        └────┘
1102  by induction l; [refl, simp only [*, concat_eq_append, cons_append, map, map_append]]; split; refl
id                                      └──────────────┘  └─────────┘  └─┘  └────────┘
src     └────────┘   └──┘  └────────────┘└──────────────┘└┘└─────────┘└┘└─┘└┘└────────┘   └───┘  └────
typ     └────────┘  └──┘  └────────────┘└──────────────┘└┘└─────────┘└┘└─┘└┘└────────┘   └───┘  └────
doc     └────────┘    └──┘  └────────────┘                └┘           └┘   └┘             └───┘  └────
txt     └────────┘    └──┘  └────────────┘                └┘           └┘   └┘             └───┘  └────
par     └────────┘    └──┘  └────────────┘                └┘           └┘   └┘             └───┘  └────
pid                            └──┘└───┘                └┘           └┘   └┘                        
st     └────────────────────────────────────────────────────────────────────────────────────────────────
1103  
src  
typ  
doc  
txt  
par  
pid  
st   
1104  theorem map_id' {f : α → α} (h : ∀ x, f x = x) (l : list α) : map f l = l :=
id                                                └──┘     └─┘    
src                                                     └──┘      └─┘     
typ                                               └──┘     └─┘    
1105  by induction l; [refl, simp only [*, map]]; split; refl
id                                      └─┘
src     └────────┘   └──┘  └────────────┘└─┘   └───┘  └────
typ     └────────┘  └──┘  └────────────┘└─┘   └───┘  └────
doc     └────────┘    └──┘  └────────────┘      └───┘  └────
txt     └────────┘    └──┘  └────────────┘      └───┘  └────
par     └────────┘    └──┘  └────────────┘      └───┘  └────
pid                            └──┘└───┘                 
st     └─────────────────────────────────────────────────────
1106  
src  
typ  
doc  
txt  
par  
pid  
st   
1107  @[simp] theorem foldl_map (g : β → γ) (f : α → γ → α) (a : α) (l : list β) :
id                                                                └──┘ 
src                                                                     └──┘
typ                                                               └──┘ 
doc    └──┘
1108    foldl f a (map g l) = foldl (λx y, f x (g y)) a l :=
id     └───┘    └─┘     └───┘              
src    └───┘      └─┘       └───┘
typ    └───┘    └─┘     └───┘              
1109  by revert a; induction l; intros; [refl, simp only [*, map, foldl]]
id                                                        └─┘  └───┘
src     └──────┘  └────────┘   └────┘  └──┘  └────────────┘└─┘└┘└───┘
typ     └──────┘  └────────┘  └────┘  └──┘  └────────────┘└─┘└┘└───┘
doc     └──────┘  └────────┘   └────┘   └──┘  └────────────┘   └┘     
txt     └──────┘  └────────┘   └────┘   └──┘  └────────────┘   └┘     
par     └──────┘  └────────┘   └────┘   └──┘  └────────────┘   └┘     
pid           └┘                                 └──┘└───┘   └┘     
st     └───────────────────────────────────────────────────────────────┘
1110  
1111  @[simp] theorem foldr_map (g : β → γ) (f : γ → α → α) (a : α) (l : list β) :
id                                                                └──┘ 
src                                                                     └──┘
typ                                                               └──┘ 
doc    └──┘
1112    foldr f a (map g l) = foldr (f ∘ g) a l :=
id     └───┘    └─┘     └───┘       
src    └───┘      └─┘       └───┘    
typ    └───┘    └─┘     └───┘       
1113  by revert a; induction l; intros; [refl, simp only [*, map, foldr]]
id                                                        └─┘  └───┘
src     └──────┘  └────────┘   └────┘  └──┘  └────────────┘└─┘└┘└───┘
typ     └──────┘  └────────┘  └────┘  └──┘  └────────────┘└─┘└┘└───┘
doc     └──────┘  └────────┘   └────┘   └──┘  └────────────┘   └┘     
txt     └──────┘  └────────┘   └────┘   └──┘  └────────────┘   └┘     
par     └──────┘  └────────┘   └────┘   └──┘  └────────────┘   └┘     
pid           └┘                                 └──┘└───┘   └┘     
st     └───────────────────────────────────────────────────────────────┘
1114  
1115  theorem foldl_hom (l : list γ) (f : α → β) (op : α → γ → α) (op' : β → γ → β) (a : α)
id                          └──┘                                               
src                         └──┘
typ                         └──┘                                               
1116    (h : ∀a x, f (op a x) = op' (f a) x) : foldl op' (f a) l = f (foldl op a l) :=
id                └┘     └─┘         └───┘ └─┘         └───┘ └┘  
src                                          └───┘                 └───┘
typ               └┘     └─┘         └───┘ └─┘         └───┘ └┘  
1117  eq.symm $ by { revert a, induction l; intros; [refl, simp only [*, foldl]] }
id   └─────┘                                                          └───┘
src  └─────┘        └──────┘  └────────┘   └────┘  └──┘  └────────────┘└───┘
typ  └─────┘        └──────┘  └────────┘  └────┘  └──┘  └────────────┘└───┘
doc                 └──────┘  └────────┘   └────┘   └──┘  └────────────┘     
txt                 └──────┘  └────────┘   └────┘   └──┘  └────────────┘     
par                 └──────┘  └────────┘   └────┘   └──┘  └────────────┘     
pid                       └┘                                 └──┘└───┘     
st               └─────────┘└─────────────────────────────────────────────────┘└─┘
1118  
1119  theorem foldr_hom (l : list γ) (f : α → β) (op : γ → α → α) (op' : γ → β → β) (a : α)
id                          └──┘                                               
src                         └──┘
typ                         └──┘                                               
1120    (h : ∀x a, f (op x a) = op' x (f a)) : foldr op' (f a) l = f (foldr op a l) :=
id                └┘     └─┘         └───┘ └─┘         └───┘ └┘  
src                                          └───┘                 └───┘
typ               └┘     └─┘         └───┘ └─┘         └───┘ └┘  
1121  by { revert a, induction l; intros; [refl, simp only [*, foldr]] }
id                                                          └───┘
src       └──────┘  └────────┘   └────┘  └──┘  └────────────┘└───┘
typ       └──────┘  └────────┘  └────┘  └──┘  └────────────┘└───┘
doc       └──────┘  └────────┘   └────┘   └──┘  └────────────┘     
txt       └──────┘  └────────┘   └────┘   └──┘  └────────────┘     
par       └──────┘  └────────┘   └────┘   └──┘  └────────────┘     
pid             └┘                                 └──┘└───┘     
st     └─────────┘└─────────────────────────────────────────────────┘└─┘
1122  
1123  theorem eq_nil_of_map_eq_nil {f : α → β} {l : list α} (h : map f l = nil) : l = nil :=
id                                               └──┘        └─┘    └─┘      └─┘
src                                                └──┘         └─┘      └─┘       └─┘
typ                                              └──┘        └─┘    └─┘      └─┘
1124  eq_nil_of_length_eq_zero $ by rw [← length_map f l, h]; refl
id   └──────────────────────┘            └────────┘    
src  └──────────────────────┘      └────┘└────────┘  └┘   └────
typ  └──────────────────────┘      └────┘└────────┘└┘  └────
doc                                └────┘            └┘   └────
txt                                └────┘            └┘   └────
par                                └────┘            └┘   └────
pid                                  └──┘            └┘       
st                                └───────────────────┘└─┘└──────
1125  
src  
typ  
doc  
txt  
par  
pid  
st   
1126  @[simp] theorem map_join (f : α → β) (L : list (list α)) :
id                                           └──┘  └──┘ 
src                                            └──┘  └──┘
typ                                          └──┘  └──┘ 
doc    └──┘
1127    map f (join L) = join (map (map f) L) :=
id     └─┘   └──┘    └──┘  └─┘  └─┘   
src    └─┘    └──┘     └──┘  └─┘  └─┘
typ    └─┘   └──┘    └──┘  └─┘  └─┘   
1128  by induction L; [refl, simp only [*, join, map, map_append]]
id                                      └──┘  └─┘  └────────┘
src     └────────┘   └──┘  └────────────┘└──┘└┘└─┘└┘└────────┘
typ     └────────┘  └──┘  └────────────┘└──┘└┘└─┘└┘└────────┘
doc     └────────┘    └──┘  └────────────┘    └┘   └┘          
txt     └────────┘    └──┘  └────────────┘    └┘   └┘          
par     └────────┘    └──┘  └────────────┘    └┘   └┘          
pid                            └──┘└───┘    └┘   └┘          
st     └────────────────────────────────────────────────────────┘
1129  
1130  theorem bind_ret_eq_map (f : α → β) (l : list α) :
id                                          └──┘ 
src                                           └──┘
typ                                         └──┘ 
1131    l.bind (list.ret ∘ f) = map f l :=
id     └───┘  └──────┘     └─┘  
src     └───┘  └──────┘      └─┘
typ    └───┘  └──────┘     └─┘  
1132  by unfold list.bind; induction l; simp only [map, join, list.ret, cons_append, nil_append, *]; split; refl
id                                               └─┘  └──┘  └──────┘  └─────────┘  └────────┘
src     └──────────────┘  └────────┘   └─────────┘└─┘└┘└──┘└┘└──────┘└┘└─────────┘└┘└────────┘└──┘  └───┘  └────
typ     └──────────────┘  └────────┘  └─────────┘└─┘└┘└──┘└┘└──────┘└┘└─────────┘└┘└────────┘└──┘  └───┘  └────
doc     └──────────────┘  └────────┘   └─────────┘   └┘    └┘        └┘           └┘          └──┘  └───┘  └────
txt     └──────────────┘  └────────┘   └─────────┘   └┘    └┘        └┘           └┘          └──┘  └───┘  └────
par     └──────────────┘  └────────┘   └─────────┘   └┘    └┘        └┘           └┘          └──┘  └───┘  └────
pid           └────────┘                  └──┘└┘   └┘    └┘        └┘           └┘          └──┘             
st     └────────────────────────────────────────────────────────────────────────────────────────────────────────
1133  
src  
typ  
doc  
txt  
par  
pid  
st   
1134  @[simp] theorem map_eq_map {α β} (f : α → β) (l : list α) : f <$> l = map f l := rfl
id                                                   └──┘      └─┘   └─┘      └─┘
src                                                    └──┘        └─┘    └─┘        └─┘
typ                                                  └──┘      └─┘   └─┘      └─┘
doc    └──┘
1135  
1136  @[simp] theorem map_tail (f : α → β) (l) : map f (tail l) = tail (map f l) :=
id                                            └─┘   └──┘    └──┘  └─┘  
src                                             └─┘    └──┘     └──┘  └─┘
typ                                           └─┘   └──┘    └──┘  └─┘  
doc    └──┘
1137  by cases l; refl
id            
src     └────┘   └────
typ     └────┘  └────
doc     └────┘   └────
txt     └────┘   └────
par     └────┘   └────
pid                 
st     └──────────────
1138  
src  
typ  
doc  
txt  
par  
pid  
st   
1139  @[simp] theorem injective_map_iff {f : α → β} : injective (map f) ↔ injective f :=
id                                                 └───────┘  └─┘    └───────┘ 
src                                                  └───────┘  └─┘     └───────┘
typ                                                └───────┘  └─┘    └───────┘ 
doc    └──┘
1140  begin
st   └─────
1141    split; intros h x y hxy,
src    └───┘  └──────────────┘
typ    └───┘  └──────────────┘
doc    └───┘  └──────────────┘
txt    └───┘  └──────────────┘
par    └───┘  └──────────────┘
pid                 └────────┘
st   ────────────────────────┘└─
1142    { suffices : [x] = [y], { simpa using this }, apply h, simp [hxy] },
id                                      └──┘                   └─┘
src      └─────────┘        └──────────┘       └────┘   └────┘   └┘
typ      └─────────┘      └──────────┘└──┘   └────┘   └────┘└─┘└┘
doc      └─────────┘           └──────────┘       └────┘   └────┘   └┘
txt      └─────────┘           └──────────┘       └────┘   └────┘   └┘
par      └─────────┘           └──────────┘       └────┘   └────┘   └┘
pid      └───────┘└┘                └────┘                      
st   ───┘└──────────────────┘└──┘└───────────────┘└┘└──────┘└───────────┘└┘
1143    { induction y generalizing x, simpa using hxy,
id                                              └─┘
src      └────────┘ └─────────────┘  └──────────┘
typ      └────────┘└─────────────┘  └──────────┘└─┘
doc      └────────┘ └─────────────┘  └──────────┘
txt      └────────┘ └─────────────┘  └──────────┘
par      └────────┘ └─────────────┘  └──────────┘
pid                └────────────┘       └────┘
st   ─────────────────────────────┘└───────────────┘└─
1144      cases x, simpa using hxy, simp at hxy, simp [y_ih hxy.2, h hxy.1] }
id                           └─┘                     └──┘ └─┘     └─┘
src      └────┘   └──────────┘     └─────────┘  └────┘       └──┘    └──┘
typ      └────┘  └──────────┘└─┘  └─────────┘  └────┘└──┘└─┘└──┘└─┘└──┘
doc      └────┘   └──────────┘     └─────────┘  └────┘       └──┘    └──┘
txt      └────┘   └──────────┘     └─────────┘  └────┘       └──┘    └──┘
par      └────┘   └──────────┘     └─────────┘  └────┘       └──┘    └──┘
pid                   └────┘         └────┘             └──┘    └─┘
st   ──────────┘└───────────────┘└───────────┘└───────────────────────────┘└─
1145  end
st   ──┘
1146  
1147  /- map₂ -/
1148  
1149  theorem nil_map₂ (f : α → β → γ) (l : list β) : map₂ f [] l = [] :=
id                                      └──┘     └──┘  └┘   └┘
src                                        └──┘      └──┘   └┘    └┘
typ                                     └──┘     └──┘  └┘   └┘
1150  by cases l; refl
id            
src     └────┘   └────
typ     └────┘  └────
doc     └────┘   └────
txt     └────┘   └────
par     └────┘   └────
pid                 
st     └──────────────
1151  
src  
typ  
doc  
txt  
par  
pid  
st   
1152  theorem map₂_nil (f : α → β → γ) (l : list α) : map₂ f l [] = [] :=
id                                      └──┘     └──┘   └┘  └┘
src                                        └──┘      └──┘     └┘  └┘
typ                                     └──┘     └──┘   └┘  └┘
1153  by cases l; refl
id            
src     └────┘   └────
typ     └────┘  └────
doc     └────┘   └────
txt     └────┘   └────
par     └────┘   └────
pid                 
st     └──────────────
1154  
src  
typ  
doc  
txt  
par  
pid  
st   
1155  /- take, drop -/
src  ────────────────┘
typ  ────────────────┘
doc  ────────────────┘
txt  ────────────────┘
par  ────────────────┘
pid  ────────────────┘
st   ────────────────┘
1156  @[simp] theorem take_zero (l : list α) : take 0 l = [] := rfl
id                                  └──┘     └──┘     └┘    └─┘
src                                 └──┘      └──┘      └┘    └─┘
typ                                 └──┘     └──┘     └┘    └─┘
doc    └──┘
1157  
1158  @[simp] theorem take_nil : ∀ n, take n [] = ([] : list α)
id                                  └──┘  └┘   └┘   └──┘ 
src                                  └──┘   └┘   └┘   └──┘
typ                                 └──┘  └┘   └┘   └──┘ 
doc    └──┘
1159  | 0     := rfl
id              └─┘
src             └─┘
typ             └─┘
1160  | (n+1) := rfl
id             └─┘
src            └─┘
typ            └─┘
1161  
1162  theorem take_cons (n) (a : α) (l : list α) : take (succ n) (a::l) = a :: take n l := rfl
id                                     └──┘     └──┘  └──┘    └┘    └┘ └──┘      └─┘
src                                     └──┘      └──┘  └──┘      └┘      └┘ └──┘        └─┘
typ                                    └──┘     └──┘  └──┘    └┘    └┘ └──┘      └─┘
1163  
1164  @[simp] theorem take_all : ∀ (l : list α), take (length l) l = l
id                                    └──┘    └──┘  └────┘     
src                                    └──┘     └──┘  └────┘      
typ                                   └──┘    └──┘  └────┘     
doc    └──┘
1165  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
1166  | (a::l) := begin change a :: (take (length l) l) = a :: l, rw take_all end
id       └┘                         └──┘  └────┘                 └──────┘
src      └┘            └─────┘    └──┘ └────┘ └┘ └┘      └─┘        
typ      └┘            └─────┘    └──┘ └────┘ └┘ └┘    └─┘└──────┘
doc                    └─────┘                └┘ └┘       └─┘        
txt                    └─────┘                └┘ └┘       └─┘        
par                    └─────┘                └┘ └┘       └─┘        
pid                                          └┘ └┘                 
st               └────────────────────────────────────────────┘└────────────┘└─┘
1167  
1168  theorem take_all_of_le : ∀ {n} {l : list α}, length l ≤ n → take n l = l
id                                     └──┘    └────┘      └──┘    
src                                      └──┘     └────┘        └──┘     
typ                                    └──┘    └────┘      └──┘    
1169  | 0     []     h := rfl
id           └┘          └─┘
src          └┘          └─┘
typ          └┘          └─┘
1170  | 0     (a::l) h := absurd h (not_le_of_gt (zero_lt_succ _))
id             └┘       └────┘    └──────────┘  └──────────┘
src            └┘        └────┘    └──────────┘  └──────────┘
typ            └┘       └────┘    └──────────┘  └──────────┘
1171  | (n+1) []     h := rfl
id          └┘          └─┘
src         └┘          └─┘
typ         └┘          └─┘
1172  | (n+1) (a::l) h :=
id            └┘
src           └┘
typ           └┘
1173    begin
st     └─────
1174      change a :: take n l = a :: l,
id                   └──┘         
src      └─────┘   └──┘     
typ      └─────┘   └──┘   
doc      └─────┘             
txt      └─────┘             
par      └─────┘             
pid                         
st   ────────────────────────────────┘└─
1175      rw [take_all_of_le (le_of_succ_le_succ h)]
id           └────────────┘  └────────────────┘ 
src      └──┘               └────────────────┘ └──
typ      └──┘└────────────┘ └────────────────┘└──
doc      └──┘                                  └──
txt      └──┘                                  └──
par      └──┘                                  └──
pid        └┘                                  └┘
st   ────────────────────────────────────────────┘
1176    end
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
1177  
1178  @[simp] theorem take_left : ∀ l₁ l₂ : list α, take (length l₁) (l₁ ++ l₂) = l₁
id                                 └┘      └──┘   └──┘  └────┘ └┘   └┘ └┘ └┘   └┘
src                                        └──┘    └──┘  └────┘         └┘     
typ                                └┘      └──┘   └──┘  └────┘ └┘   └┘ └┘ └┘   └┘
doc    └──┘
1179  | []      l₂ := rfl
id     └┘            └─┘
src    └┘            └─┘
typ    └┘            └─┘
1180  | (a::l₁) l₂ := congr_arg (cons a) (take_left l₁ l₂)
id      └┘└┘  └┘    └───────┘  └──┘     └───────┘
src      └┘          └───────┘  └──┘
typ     └┘└┘  └┘    └───────┘  └──┘     └───────┘
1181  
1182  theorem take_left' {l₁ l₂ : list α} {n} (h : length l₁ = n) :
id                               └──┘            └────┘ └┘  
src                              └──┘             └────┘    
typ                              └──┘            └────┘ └┘  
1183    take n (l₁ ++ l₂) = l₁ :=
id     └──┘   └┘ └┘ └┘   └┘
src    └──┘       └┘     
typ    └──┘   └┘ └┘ └┘   └┘
1184  by rw ← h; apply take_left
id                   └───────┘
src     └───┘   └────┘└───────┘
typ     └───┘  └────┘└───────┘
doc     └───┘   └────┘         
txt     └───┘   └────┘         
par     └───┘   └────┘         
pid       └─┘                 
st     └────────────────────────
1185  
src  
typ  
doc  
txt  
par  
pid  
st   
1186  theorem take_take : ∀ (n m) (l : list α), take n (take m l) = take (min n m) l
id                                 └──┘    └──┘   └──┘     └──┘  └─┘    
src                                   └──┘     └──┘    └──┘       └──┘  └─┘
typ                                └──┘    └──┘   └──┘     └──┘  └─┘    
1187  | n         0        l      := by rw [min_zero, take_zero, take_nil]
id                                         └──────┘  └───────┘  └──────┘
src                                    └──┘└──────┘└┘└───────┘└┘└──────┘└┘
typ                                    └──┘└──────┘└┘└───────┘└┘└──────┘└┘
doc                                    └──┘        └┘         └┘        └┘
txt                                    └──┘        └┘         └┘        └┘
par                                    └──┘        └┘         └┘        └┘
pid                                      └┘        └┘         └┘        
st                                    └───────────┘└─────────┘└────────┘
1188  | 0         m        l      := by rw [zero_min, take_zero, take_zero]
id                                         └──────┘  └───────┘  └───────┘
src                                    └──┘└──────┘└┘└───────┘└┘└───────┘└┘
typ                                    └──┘└──────┘└┘└───────┘└┘└───────┘└┘
doc                                    └──┘        └┘         └┘         └┘
txt                                    └──┘        └┘         └┘         └┘
par                                    └──┘        └┘         └┘         └┘
pid                                      └┘        └┘         └┘         
st                                    └───────────┘└─────────┘└─────────┘
1189  | (succ n)  (succ m) nil    := by simp only [take_nil]
id                └──┘    └─┘                     └──────┘
src               └──┘    └─┘          └─────────┘└──────┘└┘
typ               └──┘    └─┘          └─────────┘└──────┘└┘
doc                                    └─────────┘        └┘
txt                                    └─────────┘        └┘
par                                    └─────────┘        └┘
pid                                        └──┘└┘        
st                                    └────────────────────┘
1190  | (succ n)  (succ m) (a::l) := by simp only [take, min_succ_succ, take_take n m l]; split; refl
id                └──┘      └┘                    └──┘  └───────────┘  └───────┘   
src               └──┘      └┘         └─────────┘└──┘└┘└───────────┘└┘              └───┘  └────
typ               └──┘      └┘         └─────────┘└──┘└┘└───────────┘└┘└───────┘  └───┘  └────
doc                                    └─────────┘    └┘             └┘              └───┘  └────
txt                                    └─────────┘    └┘             └┘              └───┘  └────
par                                    └─────────┘    └┘             └┘              └───┘  └────
pid                                        └──┘└┘    └┘             └┘                         
st                                    └──────────────────────────────────────────────────────────────
1191  
src  
typ  
doc  
txt  
par  
pid  
st   
1192  @[simp] theorem drop_nil : ∀ n, drop n [] = ([] : list α)
id                                  └──┘  └┘   └┘   └──┘ 
src                                  └──┘   └┘   └┘   └──┘
typ                                 └──┘  └┘   └┘   └──┘ 
doc    └──┘
1193  | 0     := rfl
id              └─┘
src             └─┘
typ             └─┘
1194  | (n+1) := rfl
id             └─┘
src            └─┘
typ            └─┘
1195  
1196  @[simp] theorem drop_one : ∀ l : list α, drop 1 l = tail l
id                                   └──┘   └──┘     └──┘ 
src                                   └──┘    └──┘      └──┘
typ                                  └──┘   └──┘     └──┘ 
doc    └──┘
1197  | []       := rfl
id     └┘          └─┘
src    └┘          └─┘
typ    └┘          └─┘
1198  | (a :: l) := rfl
id        └┘       └─┘
src       └┘       └─┘
typ       └┘       └─┘
1199  
1200  theorem drop_add : ∀ m n (l : list α), drop (m + n) l = drop m (drop n l)
id                               └──┘    └──┘        └──┘   └──┘  
src                                └──┘     └──┘           └──┘    └──┘
typ                              └──┘    └──┘        └──┘   └──┘  
1201  | m 0     l      := rfl
id                       └─┘
src                      └─┘
typ                      └─┘
1202  | m (n+1) []     := (drop_nil _).symm
id            └┘         └──────┘   └──┘
src           └┘         └──────┘   └──┘
typ           └┘         └──────┘   └──┘
1203  | m (n+1) (a::l) := drop_add m n _
id            └┘      └──────┘
src             └┘
typ           └┘      └──────┘
1204  
1205  @[simp] theorem drop_left : ∀ l₁ l₂ : list α, drop (length l₁) (l₁ ++ l₂) = l₂
id                                 └┘      └──┘   └──┘  └────┘ └┘   └┘ └┘ └┘   └┘
src                                        └──┘    └──┘  └────┘         └┘     
typ                                └┘      └──┘   └──┘  └────┘ └┘   └┘ └┘ └┘   └┘
doc    └──┘
1206  | []      l₂ := rfl
id     └┘            └─┘
src    └┘            └─┘
typ    └┘            └─┘
1207  | (a::l₁) l₂ := drop_left l₁ l₂
id       └┘└┘  └┘    └───────┘
src      └┘
typ      └┘└┘  └┘    └───────┘
1208  
1209  theorem drop_left' {l₁ l₂ : list α} {n} (h : length l₁ = n) :
id                               └──┘            └────┘ └┘  
src                              └──┘             └────┘    
typ                              └──┘            └────┘ └┘  
1210    drop n (l₁ ++ l₂) = l₂ :=
id     └──┘   └┘ └┘ └┘   └┘
src    └──┘       └┘     
typ    └──┘   └┘ └┘ └┘   └┘
1211  by rw ← h; apply drop_left
id                   └───────┘
src     └───┘   └────┘└───────┘
typ     └───┘  └────┘└───────┘
doc     └───┘   └────┘         
txt     └───┘   └────┘         
par     └───┘   └────┘         
pid       └─┘                 
st     └────────────────────────
1212  
src  
typ  
doc  
txt  
par  
pid  
st   
1213  theorem drop_eq_nth_le_cons : ∀ {n} {l : list α} h,
id                                          └──┘   
src                                           └──┘
typ                                         └──┘   
1214    drop n l = nth_le l n h :: drop (n+1) l
id     └──┘    └────┘    └┘ └──┘     
src    └──┘      └────┘       └┘ └──┘   
typ    └──┘    └────┘    └┘ └──┘     
1215  | 0     (a::l) h := rfl
id             └┘        └─┘
src            └┘        └─┘
typ            └┘        └─┘
1216  | (n+1) (a::l) h := @drop_eq_nth_le_cons n _ _
id           └┘         └─────────────────┘
src           └┘
typ          └┘         └─────────────────┘
1217  
1218  @[simp] lemma drop_all (l : list α) : l.drop l.length = [] :=
id                               └──┘     └───┘ └─────┘  └┘
src                              └──┘       └───┘  └─────┘  └┘
typ                              └──┘     └───┘ └─────┘  └┘
doc    └──┘
1219  calc l.drop l.length = (l ++ []).drop l.length : by simp
id        └───┘ └─────┘     └┘ └┘ └──┘  └─────┘
src        └───┘  └─────┘      └┘ └┘ └──┘   └─────┘      └────
typ       └───┘ └─────┘     └┘ └┘ └──┘  └─────┘      └────
doc                                                      └────
txt                                                      └────
par                                                      └────
pid                                                          
st                                                      └─────
1220                   ... = [] : drop_left _ _
id                          └┘   └───────┘
src  ────────────────┘      └┘   └───────┘
typ  ────────────────┘      └┘   └───────┘
doc  ────────────────┘
txt  ────────────────┘
par  ────────────────┘
pid  ────────────────┘
st   ────────────────┘
1221  
1222  lemma drop_append_of_le_length : ∀ {l₁ l₂ : list α} {n : ℕ}, n ≤ l₁.length →
id                                              └──┘             └┘└─────┘
src                                              └──┘                 └─────┘
typ                                             └──┘             └┘└─────┘
1223    (l₁ ++ l₂).drop n = l₁.drop n ++ l₂
id      └┘ └┘ └┘ └──┘    └┘└───┘  └┘ └┘
src        └┘    └──┘       └───┘   └┘
typ     └┘ └┘ └┘ └──┘    └┘└───┘  └┘ └┘
1224  | l₁      l₂ 0     hn := by simp
src                              └───┘
typ                              └───┘
doc                              └───┘
txt                              └───┘
par                              └───┘
pid                                  
st                              └────┘
1225  | []      l₂ (n+1) hn := absurd hn dec_trivial
id     └┘              └┘    └────┘    └─────────┘
src    └┘                    └────┘    └─────────┘
typ    └┘              └┘    └────┘    └─────────┘
doc                                     └─────────┘
1226  | (a::l₁) l₂ (n+1) hn :=
id       └┘         
src      └┘         
typ      └┘         
1227  by rw [drop, cons_append, drop, drop_append_of_le_length (le_of_succ_le_succ hn)]
id          └──┘  └─────────┘  └──┘  └──────────────────────┘  └────────────────┘ └┘
src     └──┘└──┘└┘└─────────┘└┘└──┘└┘                         └────────────────┘  └──
typ     └──┘└──┘└┘└─────────┘└┘└──┘└┘└──────────────────────┘ └────────────────┘└┘└──
doc     └──┘    └┘           └┘    └┘                                             └──
txt     └──┘    └┘           └┘    └┘                                             └──
par     └──┘    └┘           └┘    └┘                                             └──
pid       └┘    └┘           └┘    └┘                                             └┘
st     └───────┘└───────────┘└────┘└────────────────────────────────────────────────┘
1228  
src  
typ  
doc  
txt  
par  
pid  
st   
1229  lemma take_append_of_le_length : ∀ {l₁ l₂ : list α} {n : ℕ},
id                                              └──┘        
src                                              └──┘         
typ                                             └──┘        
1230    n ≤ l₁.length → (l₁ ++ l₂).take n = l₁.take n
id       └┘└─────┘    └┘ └┘ └┘ └──┘    └┘└───┘ 
src         └─────┘       └┘    └──┘       └───┘
typ      └┘└─────┘    └┘ └┘ └┘ └──┘    └┘└───┘ 
1231  | l₁      l₂ 0     hn := by simp
src                              └───┘
typ                              └───┘
doc                              └───┘
txt                              └───┘
par                              └───┘
pid                                  
st                              └────┘
1232  | []      l₂ (n+1) hn := absurd hn dec_trivial
id     └┘              └┘    └────┘    └─────────┘
src    └┘                    └────┘    └─────────┘
typ    └┘              └┘    └────┘    └─────────┘
doc                                     └─────────┘
1233  | (a::l₁) l₂ (n+1) hn :=
id       └┘         
src      └┘         
typ      └┘         
1234  by rw [list.take, list.cons_append, list.take, take_append_of_le_length (le_of_succ_le_succ hn)]
id          └───────┘  └──────────────┘  └───────┘  └──────────────────────┘  └────────────────┘ └┘
src     └──┘└───────┘└┘└──────────────┘└┘└───────┘└┘                         └────────────────┘  └──
typ     └──┘└───────┘└┘└──────────────┘└┘└───────┘└┘└──────────────────────┘ └────────────────┘└┘└──
doc     └──┘         └┘                └┘         └┘                                             └──
txt     └──┘         └┘                └┘         └┘                                             └──
par     └──┘         └┘                └┘         └┘                                             └──
pid       └┘         └┘                └┘         └┘                                             └┘
st     └────────────┘└────────────────┘└─────────┘└────────────────────────────────────────────────┘
1235  
src  
typ  
doc  
txt  
par  
pid  
st   
1236  @[simp] theorem drop_drop (n : ℕ) : ∀ (m) (l : list α), drop n (drop m l) = drop (n + m) l
id                                               └──┘    └──┘   └──┘     └──┘      
src                                                └──┘     └──┘    └──┘       └──┘    
typ                                              └──┘    └──┘   └──┘     └──┘      
doc    └──┘
1237  | m     []     := by simp
id           └┘
src          └┘           └───┘
typ          └┘           └───┘
doc                       └───┘
txt                       └───┘
par                       └───┘
pid                           
st                       └────┘
1238  | 0     l      := by simp
src                       └───┘
typ                       └───┘
doc                       └───┘
txt                       └───┘
par                       └───┘
pid                           
st                       └────┘
1239  | (m+1) (a::l) :=
id          └┘
src           └┘
typ         └┘
1240    calc drop n (drop (m + 1) (a :: l)) = drop n (drop m l) : rfl
id          └──┘   └──┘           └┘       └──┘   └──┘        └─┘
src         └──┘    └──┘           └┘       └──┘    └──┘        └─┘
typ         └──┘   └──┘           └┘       └──┘   └──┘        └─┘
1241      ... = drop (n + m) l : drop_drop m l
id             └──┘           └───────┘
src            └──┘    
typ            └──┘           └───────┘
1242      ... = drop (n + (m + 1)) (a :: l) : rfl
id             └──┘               └┘      └─┘
src            └──┘                └┘      └─┘
typ            └──┘               └┘      └─┘
1243  
1244  theorem drop_take : ∀ (m : ℕ) (n : ℕ) (l : list α),
id                                           └──┘ 
src                                           └──┘
typ                                          └──┘ 
1245    drop m (take (m + n) l) = take n (drop m l)
id     └──┘   └──┘         └──┘   └──┘  
src    └──┘    └──┘            └──┘    └──┘
typ    └──┘   └──┘         └──┘   └──┘  
1246  | 0     n _      := by simp
src                         └───┘
typ                         └───┘
doc                         └───┘
txt                         └───┘
par                         └───┘
pid                             
st                         └────┘
1247  | (m+1) n nil    := by simp
id            └─┘
src           └─┘          └───┘
typ           └─┘          └───┘
doc                         └───┘
txt                         └───┘
par                         └───┘
pid                             
st                         └────┘
1248  | (m+1) n (_::l) :=
id            └┘
src             └┘
typ           └┘
1249    have h: m + 1 + n = (m+n) + 1, by simp,
id                           
src                                 └──┘
typ                                 └──┘
doc                                      └──┘
txt                                      └──┘
par                                      └──┘
st                                      └───┘
1250    by simpa [take_cons, h] using drop_take m n l
id               └───────┘          └───────┘   
src       └─────┘└───────┘└┘ └──────┘            
typ       └─────┘└───────┘└┘└──────┘└───────┘
doc       └─────┘         └┘ └──────┘            
txt       └─────┘         └┘ └──────┘            
par       └─────┘         └┘ └──────┘            
pid                     └┘ └────┘            
st       └───────────────────────────────────────────
1251  
src  
typ  
doc  
txt  
par  
pid  
st   
1252  theorem modify_nth_tail_eq_take_drop (f : list α → list α) (H : f [] = []) :
id                                             └──┘    └──┘         └┘  └┘
src                                            └──┘     └──┘           └┘  └┘
typ                                            └──┘    └──┘         └┘  └┘
1253    ∀ n l, modify_nth_tail f n l = take n l ++ f (drop n l)
id          └─────────────┘     └──┘   └┘   └──┘  
src           └─────────────┘        └──┘     └┘    └──┘
typ         └─────────────┘     └──┘   └┘   └──┘  
doc           └─────────────┘
1254  | 0     l      := rfl
id                     └─┘
src                    └─┘
typ                    └─┘
1255  | (n+1) []     := H.symm
id          └┘        └───┘
src         └┘         └───┘
typ         └┘        └───┘
1256  | (n+1) (b::l) := congr_arg (cons b) (modify_nth_tail_eq_take_drop n l)
id          └┘     └───────┘  └──┘     └──────────────────────────┘
src           └┘      └───────┘  └──┘
typ         └┘     └───────┘  └──┘     └──────────────────────────┘
1257  
1258  theorem modify_nth_eq_take_drop (f : α → α) :
id                                           
typ                                          
1259    ∀ n l, modify_nth f n l = take n l ++ modify_head f (drop n l) :=
id          └────────┘     └──┘   └┘ └─────────┘   └──┘  
src           └────────┘        └──┘     └┘ └─────────┘    └──┘
typ         └────────┘     └──┘   └┘ └─────────┘   └──┘  
doc           └────────┘                     └─────────┘
1260  modify_nth_tail_eq_take_drop _ rfl
id   └──────────────────────────┘   └─┘
src  └──────────────────────────┘   └─┘
typ  └──────────────────────────┘   └─┘
1261  
1262  theorem modify_nth_eq_take_cons_drop (f : α → α) {n l} (h) :
id                                                
typ                                               
1263    modify_nth f n l = take n l ++ f (nth_le l n h) :: drop (n+1) l :=
id     └────────┘     └──┘   └┘   └────┘     └┘ └──┘     
src    └────────┘        └──┘     └┘    └────┘        └┘ └──┘   
typ    └────────┘     └──┘   └┘   └────┘     └┘ └──┘     
doc    └────────┘
1264  by rw [modify_nth_eq_take_drop, drop_eq_nth_le_cons h]; refl
id          └─────────────────────┘  └─────────────────┘ 
src     └──┘└─────────────────────┘└┘└─────────────────┘   └────
typ     └──┘└─────────────────────┘└┘└─────────────────┘  └────
doc     └──┘                       └┘                      └────
txt     └──┘                       └┘                      └────
par     └──┘                       └┘                      └────
pid       └┘                       └┘                          
st     └──────────────────────────┘└─────────────────────┘└──────
1265  
src  
typ  
doc  
txt  
par  
pid  
st   
1266  theorem update_nth_eq_take_cons_drop (a : α) {n l} (h : n < length l) :
id                                                            └────┘ 
src                                                             └────┘
typ                                                           └────┘ 
1267    update_nth l n a = take n l ++ a :: drop (n+1) l :=
id     └────────┘     └──┘   └┘  └┘ └──┘     
src    └────────┘        └──┘     └┘   └┘ └──┘   
typ    └────────┘     └──┘   └┘  └┘ └──┘     
1268  by rw [update_nth_eq_modify_nth, modify_nth_eq_take_cons_drop _ h]
id          └──────────────────────┘  └──────────────────────────┘   
src     └──┘└──────────────────────┘└┘└──────────────────────────┘└─┘ └─
typ     └──┘└──────────────────────┘└┘└──────────────────────────┘└─┘└─
doc     └──┘                        └┘                            └─┘ └─
txt     └──┘                        └┘                            └─┘ └─
par     └──┘                        └┘                            └─┘ └─
pid       └┘                        └┘                            └─┘ 
st     └───────────────────────────┘└────────────────────────────────┘
1269  
src  
typ  
doc  
txt  
par  
pid  
st   
1270  @[simp] lemma update_nth_eq_nil (l : list α) (n : ℕ) (a : α) : l.update_nth n a = [] ↔ l = [] :=
id                                        └──┘                   └─────────┘    └┘    └┘
src                                       └──┘                      └─────────┘      └┘     └┘
typ                                       └──┘                   └─────────┘    └┘    └┘
doc    └──┘
1271  by cases l; cases n; simp only [update_nth]
id                                 └────────┘
src     └────┘   └────┘   └─────────┘└────────┘└─
typ     └────┘  └────┘  └─────────┘└────────┘└─
doc     └────┘   └────┘   └─────────┘          └─
txt     └────┘   └────┘   └─────────┘          └─
par     └────┘   └────┘   └─────────┘          └─
pid                         └──┘└┘          
st     └─────────────────────────────────────────
1272  
src  
typ  
doc  
txt  
par  
pid  
st   
1273  section take'
1274  variable [inhabited α]
id             └───────┘
src            └───────┘
typ            └───────┘
1275  
1276  @[simp] theorem take'_length : ∀ n l, length (@take' α _ n l) = n
id                                       └────┘   └───┘        
src                                        └────┘   └───┘          
typ                                      └────┘   └───┘        
doc    └──┘
1277  | 0     l := rfl
id                └─┘
src               └─┘
typ               └─┘
1278  | (n+1) l := congr_arg succ (take'_length _ _)
id               └───────┘ └──┘  └──────────┘
src              └───────┘ └──┘
typ              └───────┘ └──┘  └──────────┘
1279  
1280  @[simp] theorem take'_nil : ∀ n, take' n (@nil α) = repeat (default _) n
id                                   └───┘    └─┘    └────┘  └─────┘    
src                                   └───┘     └─┘     └────┘  └─────┘
typ                                  └───┘    └─┘    └────┘  └─────┘    
doc    └──┘
1281  | 0     := rfl
id              └─┘
src             └─┘
typ             └─┘
1282  | (n+1) := congr_arg (cons _) (take'_nil _)
id             └───────┘  └──┘     └───────┘
src            └───────┘  └──┘
typ            └───────┘  └──┘     └───────┘
1283  
1284  theorem take'_eq_take : ∀ {n} {l : list α},
id                                    └──┘ 
src                                     └──┘
typ                                   └──┘ 
1285    n ≤ length l → take' n l = take n l
id       └────┘    └───┘    └──┘  
src       └────┘     └───┘      └──┘
typ      └────┘    └───┘    └──┘  
1286  | 0     l      h := rfl
id                       └─┘
src                      └─┘
typ                      └─┘
1287  | (n+1) (a::l) h := congr_arg (cons _) $
id            └┘       └───────┘  └──┘
src           └┘        └───────┘  └──┘
typ           └┘       └───────┘  └──┘
1288    take'_eq_take $ le_of_succ_le_succ h
id     └───────────┘   └────────────────┘
src                    └────────────────┘
typ    └───────────┘   └────────────────┘
1289  
1290  @[simp] theorem take'_left (l₁ l₂ : list α) : take' (length l₁) (l₁ ++ l₂) = l₁ :=
id                                       └──┘     └───┘  └────┘ └┘   └┘ └┘ └┘   └┘
src                                      └──┘      └───┘  └────┘         └┘     
typ                                      └──┘     └───┘  └────┘ └┘   └┘ └┘ └┘   └┘
doc    └──┘
1291  (take'_eq_take (by simp only [length_append, nat.le_add_right])).trans (take_left _ _)
id    └───────────┘                └───────────┘  └──────────────┘   └───┘   └───────┘
src   └───────────┘     └─────────┘└───────────┘└┘└──────────────┘  └───┘   └───────┘
typ   └───────────┘     └─────────┘└───────────┘└┘└──────────────┘  └───┘   └───────┘
doc                     └─────────┘             └┘                
txt                     └─────────┘             └┘                
par                     └─────────┘             └┘                
pid                         └──┘└┘             └┘                
st                     └──────────────────────────────────────────┘
1292  
1293  theorem take'_left' {l₁ l₂ : list α} {n} (h : length l₁ = n) :
id                                └──┘            └────┘ └┘  
src                               └──┘             └────┘    
typ                               └──┘            └────┘ └┘  
1294    take' n (l₁ ++ l₂) = l₁ :=
id     └───┘   └┘ └┘ └┘   └┘
src    └───┘       └┘     
typ    └───┘   └┘ └┘ └┘   └┘
1295  by rw ← h; apply take'_left
id                   └────────┘
src     └───┘   └────┘└────────┘
typ     └───┘  └────┘└────────┘
doc     └───┘   └────┘          
txt     └───┘   └────┘          
par     └───┘   └────┘          
pid       └─┘                  
st     └─────────────────────────
1296  
src  
typ  
doc  
txt  
par  
pid  
st   
1297  end take'
1298  
1299  /- foldl, foldr -/
1300  
1301  lemma foldl_ext (f g : α → β → α) (a : α)
id                                       
typ                                      
1302    {l : list β} (H : ∀ a : α, ∀ b ∈ l, f a b = g a b) :
id          └──┘                             
src         └──┘                                 
typ         └──┘                             
1303    foldl f a l = foldl g a l :=
id     └───┘     └───┘   
src    └───┘        └───┘
typ    └───┘     └───┘   
1304  begin
st   └─────
1305    induction l with hd tl ih generalizing a, {refl},
id               
src    └────────┘ └───────────────────────────┘   └──┘
typ    └────────┘└───────────────────────────┘   └──┘
doc    └────────┘ └───────────────────────────┘   └──┘
txt    └────────┘ └───────────────────────────┘   └──┘
par    └────────┘ └───────────────────────────┘   └──┘
pid              └───────────┘└─────────────┘
st   ─────────────────────────────────────────┘└─────┘└┘
1306    unfold foldl,
src    └──────────┘
typ    └──────────┘
doc    └──────────┘
txt    └──────────┘
par    └──────────┘
pid          └────┘
st   ─────────────┘└─
1307    rw [ih (λ a b bin, H a b $ mem_cons_of_mem _ bin), H a hd (mem_cons_self _ _)]
id         └┘                    └─────────────┘           └┘  └───────────┘
src    └──┘    └────────┘    └─────────────┘└─┘   └─┘     └───────────┘└─────┘
typ    └──┘└┘  └────────┘   └─────────────┘└─┘   └─┘└┘ └───────────┘└─────┘
doc    └──┘    └────────┘                   └─┘   └─┘                  └─────┘
txt    └──┘    └────────┘                   └─┘   └─┘                  └─────┘
par    └──┘    └────────┘                   └─┘   └─┘                  └─────┘
pid      └┘    └────────┘                   └─┘   └─┘                  └────┘
st   ──────────────────────────────────────────────────┘└──────────────────────────┘
1308  end
st   └─┘
1309  
1310  lemma foldr_ext (f g : α → β → β) (b : β)
id                                       
typ                                      
1311    {l : list α} (H : ∀ a ∈ l, ∀ b : β, f a b = g a b) :
id          └──┘                             
src         └──┘                                 
typ         └──┘                             
1312    foldr f b l = foldr g b l :=
id     └───┘     └───┘   
src    └───┘        └───┘
typ    └───┘     └───┘   
1313  begin
st   └─────
1314    induction l with hd tl ih, {refl},
id               
src    └────────┘ └────────────┘   └──┘
typ    └────────┘└────────────┘   └──┘
doc    └────────┘ └────────────┘   └──┘
txt    └────────┘ └────────────┘   └──┘
par    └────────┘ └────────────┘   └──┘
pid              └───────────┘
st   ──────────────────────────┘└─────┘└┘
1315    simp only [mem_cons_iff, or_imp_distrib, forall_and_distrib, forall_eq] at H,
id                └──────────┘  └────────────┘  └────────────────┘  └───────┘
src    └─────────┘└──────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└────┘
typ    └─────────┘└──────────┘└┘└────────────┘└┘└────────────────┘└┘└───────┘└────┘
doc    └─────────┘            └┘              └┘                  └┘         └────┘
txt    └─────────┘            └┘              └┘                  └┘         └────┘
par    └─────────┘            └┘              └┘                  └┘         └────┘
pid        └──┘└┘            └┘              └┘                  └┘         └──┘
st   ─────────────────────────────────────────────────────────────────────────────┘└─
1316    simp only [foldr, ih H.2, H.1]
id                └───┘  └┘     
src    └─────────┘└───┘└┘   └──┘ └──┘
typ    └─────────┘└───┘└┘└┘└──┘└──┘
doc    └─────────┘     └┘   └──┘ └──┘
txt    └─────────┘     └┘   └──┘ └──┘
par    └─────────┘     └┘   └──┘ └──┘
pid        └──┘└┘     └┘   └──┘ └─┘
st   ────────────────────────────────┘
1317  end
st   └─┘
1318  
1319  @[simp] theorem foldl_nil (f : α → β → α) (a : α) : foldl f a [] = a := rfl
id                                                   └───┘   └┘      └─┘
src                                                      └───┘     └┘       └─┘
typ                                                  └───┘   └┘      └─┘
doc    └──┘
1320  
1321  @[simp] theorem foldl_cons (f : α → β → α) (a : α) (b : β) (l : list β) :
id                                                              └──┘ 
src                                                                  └──┘
typ                                                             └──┘ 
doc    └──┘
1322    foldl f a (b::l) = foldl f (f a b) l := rfl
id     └───┘    └┘   └───┘           └─┘
src    └───┘       └┘    └───┘                └─┘
typ    └───┘    └┘   └───┘           └─┘
1323  
1324  @[simp] theorem foldr_nil (f : α → β → β) (b : β) : foldr f b [] = b := rfl
id                                                   └───┘   └┘      └─┘
src                                                      └───┘     └┘       └─┘
typ                                                  └───┘   └┘      └─┘
doc    └──┘
1325  
1326  @[simp] theorem foldr_cons (f : α → β → β) (b : β) (a : α) (l : list α) :
id                                                              └──┘ 
src                                                                  └──┘
typ                                                             └──┘ 
doc    └──┘
1327    foldr f b (a::l) = f a (foldr f b l) := rfl
id     └───┘    └┘      └───┘        └─┘
src    └───┘       └┘         └───┘           └─┘
typ    └───┘    └┘      └───┘        └─┘
1328  
1329  @[simp] theorem foldl_append (f : α → β → α) :
id                                           
typ                                          
doc    └──┘
1330    ∀ (a : α) (l₁ l₂ : list β), foldl f a (l₁++l₂) = foldl f (foldl f a l₁) l₂
id                      └──┘    └───┘    └┘└┘└┘   └───┘   └───┘   └┘  └┘
src                       └──┘     └───┘        └┘     └───┘    └───┘
typ                     └──┘    └───┘    └┘└┘└┘   └───┘   └───┘   └┘  └┘
1331  | a []      l₂ := rfl
id       └┘            └─┘
src      └┘            └─┘
typ      └┘            └─┘
1332  | a (b::l₁) l₂ := by simp only [cons_append, foldl_cons, foldl_append (f a b) l₁ l₂]
id         └┘                        └─────────┘  └────────┘  └──────────┘      └┘ └┘
src        └┘             └─────────┘└─────────┘└┘└────────┘└┘                └┘    └─
typ        └┘             └─────────┘└─────────┘└┘└────────┘└┘└──────────┘ └┘└┘└┘└─
doc                       └─────────┘           └┘          └┘                └┘    └─
txt                       └─────────┘           └┘          └┘                └┘    └─
par                       └─────────┘           └┘          └┘                └┘    └─
pid                           └──┘└┘           └┘          └┘                └┘    
st                       └────────────────────────────────────────────────────────────────
1333  
src  
typ  
doc  
txt  
par  
pid  
st   
1334  @[simp] theorem foldr_append (f : α → β → β) :
id                                           
typ                                          
doc    └──┘
1335    ∀ (b : β) (l₁ l₂ : list α), foldr f b (l₁++l₂) = foldr f (foldr f b l₂) l₁
id                      └──┘    └───┘    └┘└┘└┘   └───┘   └───┘   └┘  └┘
src                       └──┘     └───┘        └┘     └───┘    └───┘
typ                     └──┘    └───┘    └┘└┘└┘   └───┘   └───┘   └┘  └┘
1336  | b []      l₂ := rfl
id       └┘            └─┘
src      └┘            └─┘
typ      └┘            └─┘
1337  | b (a::l₁) l₂ := by simp only [cons_append, foldr_cons, foldr_append b l₁ l₂]
id         └┘                        └─────────┘  └────────┘  └──────────┘  └┘ └┘
src        └┘             └─────────┘└─────────┘└┘└────────┘└┘                 └─
typ        └┘             └─────────┘└─────────┘└┘└────────┘└┘└──────────┘└┘└┘└─
doc                       └─────────┘           └┘          └┘                 └─
txt                       └─────────┘           └┘          └┘                 └─
par                       └─────────┘           └┘          └┘                 └─
pid                           └──┘└┘           └┘          └┘                 
st                       └──────────────────────────────────────────────────────────
1338  
src  
typ  
doc  
txt  
par  
pid  
st   
1339  @[simp] theorem foldl_join (f : α → β → α) :
id                                         
typ                                        
doc    └──┘
1340    ∀ (a : α) (L : list (list β)), foldl f a (join L) = foldl (foldl f) a L
id                  └──┘  └──┘     └───┘    └──┘    └───┘  └───┘    
src                   └──┘  └──┘      └───┘      └──┘     └───┘  └───┘
typ                 └──┘  └──┘     └───┘    └──┘    └───┘  └───┘    
1341  | a []     := rfl
id       └┘        └─┘
src      └┘        └─┘
typ      └┘        └─┘
1342  | a (l::L) := by simp only [join, foldl_append, foldl_cons, foldl_join (foldl f a l) L]
id         └┘                    └──┘  └──────────┘  └────────┘  └────────┘  └───┘     
src        └┘         └─────────┘└──┘└┘└──────────┘└┘└────────┘└┘           └───┘   └┘ └─
typ        └┘         └─────────┘└──┘└┘└──────────┘└┘└────────┘└┘└────────┘ └───┘└┘└─
doc                   └─────────┘    └┘            └┘          └┘                   └┘ └─
txt                   └─────────┘    └┘            └┘          └┘                   └┘ └─
par                   └─────────┘    └┘            └┘          └┘                   └┘ └─
pid                       └──┘└┘    └┘            └┘          └┘                   └┘ 
st                   └───────────────────────────────────────────────────────────────────────
1343  
src  
typ  
doc  
txt  
par  
pid  
st   
1344  @[simp] theorem foldr_join (f : α → β → β) :
id                                         
typ                                        
doc    └──┘
1345    ∀ (b : β) (L : list (list α)), foldr f b (join L) = foldr (λ l b, foldr f b l) b L
id                  └──┘  └──┘     └───┘    └──┘    └───┘       └───┘      
src                   └──┘  └──┘      └───┘      └──┘     └───┘         └───┘
typ                 └──┘  └──┘     └───┘    └──┘    └───┘       └───┘      
1346  | a []     := rfl
id       └┘        └─┘
src      └┘        └─┘
typ      └┘        └─┘
1347  | a (l::L) := by simp only [join, foldr_append, foldr_join a L, foldr_cons]
id         └┘                    └──┘  └──────────┘  └────────┘    └────────┘
src        └┘         └─────────┘└──┘└┘└──────────┘└┘            └┘└────────┘└─
typ        └┘         └─────────┘└──┘└┘└──────────┘└┘└────────┘└┘└────────┘└─
doc                   └─────────┘    └┘            └┘            └┘          └─
txt                   └─────────┘    └┘            └┘            └┘          └─
par                   └─────────┘    └┘            └┘            └┘          └─
pid                       └──┘└┘    └┘            └┘            └┘          
st                   └───────────────────────────────────────────────────────────
1348  
src  
typ  
doc  
txt  
par  
pid  
st   
1349  theorem foldl_reverse (f : α → β → α) (a : α) (l : list β) : foldl f a (reverse l) = foldr (λx y, f y x) a l :=
id                                                  └──┘     └───┘    └─────┘    └───┘           
src                                                     └──┘      └───┘      └─────┘     └───┘
typ                                                 └──┘     └───┘    └─────┘    └───┘           
1350  by induction l; [refl, simp only [*, reverse_cons, foldl_append, foldl_cons, foldl_nil, foldr]]
id                                      └──────────┘  └──────────┘  └────────┘  └───────┘  └───┘
src     └────────┘   └──┘  └────────────┘└──────────┘└┘└──────────┘└┘└────────┘└┘└───────┘└┘└───┘
typ     └────────┘  └──┘  └────────────┘└──────────┘└┘└──────────┘└┘└────────┘└┘└───────┘└┘└───┘
doc     └────────┘    └──┘  └────────────┘            └┘            └┘          └┘         └┘     
txt     └────────┘    └──┘  └────────────┘            └┘            └┘          └┘         └┘     
par     └────────┘    └──┘  └────────────┘            └┘            └┘          └┘         └┘     
pid                            └──┘└───┘            └┘            └┘          └┘         └┘     
st     └───────────────────────────────────────────────────────────────────────────────────────────┘
1351  
1352  theorem foldr_reverse (f : α → β → β) (a : β) (l : list α) : foldr f a (reverse l) = foldl (λx y, f y x) a l :=
id                                                  └──┘     └───┘    └─────┘    └───┘           
src                                                     └──┘      └───┘      └─────┘     └───┘
typ                                                 └──┘     └───┘    └─────┘    └───┘           
1353  let t := foldl_reverse (λx y, f y x) a (reverse l) in
id           └───────────┘            └─────┘ 
src           └───────────┘                  └─────┘
typ          └───────────┘            └─────┘ 
1354  by rw reverse_reverse l at t; rwa t
id         └─────────────┘            
src     └─┘└─────────────┘ └───┘  └──┘ 
typ     └─┘└─────────────┘└───┘  └──┘
doc     └─┘                └───┘  └──┘ 
txt     └─┘                └───┘  └──┘ 
par     └─┘                └───┘  └──┘ 
pid                       └───┘      
st     └──────────────────────────────┘
1355  
src  
typ  
doc  
txt  
par  
pid  
st   
1356  @[simp] theorem foldr_eta : ∀ (l : list α), foldr cons [] l = l
id                                     └──┘    └───┘ └──┘ └┘   
src                                     └──┘     └───┘ └──┘ └┘   
typ                                    └──┘    └───┘ └──┘ └┘   
doc    └──┘
1357  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
1358  | (x::l) := by simp only [foldr_cons, foldr_eta l]; split; refl
id       └┘                    └────────┘  └───────┘ 
src      └┘         └─────────┘└────────┘└┘            └───┘  └────
typ      └┘         └─────────┘└────────┘└┘└───────┘  └───┘  └────
doc                 └─────────┘          └┘            └───┘  └────
txt                 └─────────┘          └┘            └───┘  └────
par                 └─────────┘          └┘            └───┘  └────
pid                     └──┘└┘          └┘                       
st                 └─────────────────────────────────────────────────
1359  
src  
typ  
doc  
txt  
par  
pid  
st   
1360  @[simp] theorem reverse_foldl {l : list α} : reverse (foldl (λ t h, h :: t) [] l) = l :=
id                                      └──┘     └─────┘  └───┘        └┘   └┘    
src                                     └──┘      └─────┘  └───┘           └┘    └┘    
typ                                     └──┘     └─────┘  └───┘        └┘   └┘    
doc    └──┘
1361  by rw ←foldr_reverse; simp
id          └───────────┘
src     └──┘└───────────┘  └────
typ     └──┘└───────────┘  └────
doc     └──┘               └────
txt     └──┘               └────
par     └──┘               └────
pid       └┘                   
st     └────────────────────────
1362  
src  
typ  
doc  
txt  
par  
pid  
st   
1363  /- scanl -/
src  ────────────
typ  ────────────
doc  ────────────
txt  ────────────
par  ────────────
pid  ────────────
st   ────────────
1364  
src  
typ  
doc  
txt  
par  
pid  
st   
1365  lemma length_scanl {β : Type*} {f : α → β → α} :
id                                             
typ                                            
1366    ∀ a l, length (scanl f a l) = l.length + 1
id          └────┘  └───┘      └─────┘ 
src           └────┘  └───┘          └─────┘ 
typ         └────┘  └───┘      └─────┘ 
doc                   └───┘
1367  | a [] := rfl
id       └┘    └─┘
src      └┘    └─┘
typ      └┘    └─┘
1368  | a (x :: l) := by erw [length_cons, length_cons, length_scanl]
id          └┘               └─────────┘  └─────────┘  └──────────┘
src         └┘          └───┘└─────────┘└┘└─────────┘└┘            └─
typ         └┘          └───┘└─────────┘└┘└─────────┘└┘└──────────┘└─
doc                     └───┘           └┘           └┘            └─
txt                     └───┘           └┘           └┘            └─
par                     └───┘           └┘           └┘            └─
pid                        └┘           └┘           └┘            
st                     └───────────────┘└───────────┘└────────────┘
1369  
src  
typ  
doc  
txt  
par  
pid  
st   
1370  /- scanr -/
src  ────────────
typ  ────────────
doc  ────────────
txt  ────────────
par  ────────────
pid  ────────────
st   ────────────
1371  
src  
typ  
doc  
txt  
par  
pid  
st   
1372  @[simp] theorem scanr_nil (f : α → β → β) (b : β) : scanr f b [] = [b] := rfl
id                                                   └───┘   └┘      └─┘
src                                                      └───┘     └┘       └─┘
typ                                                  └───┘   └┘      └─┘
doc    └──┘                                              └───┘
1373  
1374  @[simp] theorem scanr_aux_cons (f : α → β → β) (b : β) : ∀ (a : α) (l : list α),
id                                                                     └──┘ 
src                                                                          └──┘
typ                                                                    └──┘ 
doc    └──┘
1375    scanr_aux f b (a::l) = (foldr f b (a::l), scanr f b l)
id     └───────┘    └┘   └───┘    └┘   └───┘   
src    └───────┘       └┘    └───┘       └┘    └───┘
typ    └───────┘    └┘   └───┘    └┘   └───┘   
doc                                              └───┘
1376  | a []     := rfl
id       └┘        └─┘
src      └┘        └─┘
typ      └┘        └─┘
1377  | a (x::l) := let t := scanr_aux_cons x l in
id        └┘             └────────────┘
src        └┘
typ       └┘             └────────────┘
1378    by simp only [scanr, scanr_aux, t, foldr_cons]
id                   └───┘  └───────┘    └────────┘
src       └─────────┘└───┘└┘└───────┘└┘ └┘└────────┘└─
typ       └─────────┘└───┘└┘└───────┘└┘└┘└────────┘└─
doc       └─────────┘└───┘└┘         └┘ └┘          └─
txt       └─────────┘     └┘         └┘ └┘          └─
par       └─────────┘     └┘         └┘ └┘          └─
pid           └──┘└┘     └┘         └┘ └┘          
st       └────────────────────────────────────────────
1379  
src  
typ  
doc  
txt  
par  
pid  
st   
1380  @[simp] theorem scanr_cons (f : α → β → β) (b : β) (a : α) (l : list α) :
id                                                              └──┘ 
src                                                                  └──┘
typ                                                             └──┘ 
doc    └──┘
1381    scanr f b (a::l) = foldr f b (a::l) :: scanr f b l :=
id     └───┘    └┘   └───┘    └┘  └┘ └───┘   
src    └───┘       └┘    └───┘       └┘   └┘ └───┘
typ    └───┘    └┘   └───┘    └┘  └┘ └───┘   
doc    └───┘                                  └───┘
1382  by simp only [scanr, scanr_aux_cons, foldr_cons]; split; refl
id                 └───┘  └────────────┘  └────────┘
src     └─────────┘└───┘└┘└────────────┘└┘└────────┘  └───┘  └────
typ     └─────────┘└───┘└┘└────────────┘└┘└────────┘  └───┘  └────
doc     └─────────┘└───┘└┘              └┘            └───┘  └────
txt     └─────────┘     └┘              └┘            └───┘  └────
par     └─────────┘     └┘              └┘            └───┘  └────
pid         └──┘└┘     └┘              └┘                       
st     └───────────────────────────────────────────────────────────
1383  
src  
typ  
doc  
txt  
par  
pid  
st   
1384  section foldl_eq_foldr
1385    -- foldl and foldr coincide when f is commutative and associative
1386    variables {f : α → α → α} (hcomm : commutative f) (hassoc : associative f)
id                                        └─────────┘              └─────────┘
src                                       └─────────┘              └─────────┘
typ                                       └─────────┘              └─────────┘
1387  
1388    include hassoc
1389    theorem foldl1_eq_foldr1 : ∀ a b l, foldl f a (l++[b]) = foldr f b (a::l)
id                                      └───┘    └┘   └───┘    └┘
src                                        └───┘       └┘    └───┘       └┘
typ                                     └───┘    └┘   └───┘    └┘
1390    | a b nil      := rfl
id           └─┘         └─┘
src          └─┘         └─┘
typ          └─┘         └─┘
1391    | a b (c :: l) := by simp only [cons_append, foldl_cons, foldr_cons, foldl1_eq_foldr1 _ _ l]; rw hassoc
id              └┘                     └─────────┘  └────────┘  └────────┘  └──────────────┘           └────┘
src             └┘          └─────────┘└─────────┘└┘└────────┘└┘└────────┘└┘                └───┘   └─┘      
typ             └┘          └─────────┘└─────────┘└┘└────────┘└┘└────────┘└┘└──────────────┘└───┘  └─┘└────┘
doc                         └─────────┘           └┘          └┘          └┘                └───┘   └─┘      
txt                         └─────────┘           └┘          └┘          └┘                └───┘   └─┘      
par                         └─────────┘           └┘          └┘          └┘                └───┘   └─┘      
pid                             └──┘└┘           └┘          └┘          └┘                └───┘           
st                         └───────────────────────────────────────────────────────────────────────────┘└────┘
1392  
src  
typ  
doc  
txt  
par  
pid  
st   
1393    include hcomm
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘
1394    theorem foldl_eq_of_comm_of_assoc : ∀ a b l, foldl f a (b::l) = f b (foldl f a l)
id                                               └───┘    └┘      └───┘   
src                                                 └───┘       └┘         └───┘
typ                                              └───┘    └┘      └───┘   
1395    | a b  nil    := hcomm a b
id          └─┘       └───┘
src           └─┘
typ         └─┘       └───┘
1396    | a b  (c::l) := by simp only [foldl_cons];
id              └┘                    └────────┘
src             └┘         └─────────┘└────────┘
typ             └┘         └─────────┘└────────┘
doc                        └─────────┘          
txt                        └─────────┘          
par                        └─────────┘          
pid                            └──┘└┘          
st                        └────────────────────────
1397      rw [← foldl_eq_of_comm_of_assoc, right_comm _ hcomm hassoc]; refl
id             └───────────────────────┘  └────────┘   └───┘ └────┘
src      └────┘                         └┘└────────┘└─┘             └────
typ      └────┘└───────────────────────┘└┘└────────┘└─┘└───┘└────┘  └────
doc      └────┘                         └┘          └─┘             └────
txt      └────┘                         └┘          └─┘             └────
par      └────┘                         └┘          └─┘             └────
pid        └──┘                         └┘          └─┘                 
st   ───────┘└─────────────────────────┘└─────────────────────────┘└──────
1398  
src  
typ  
doc  
txt  
par  
pid  
st   
1399    theorem foldl_eq_foldr : ∀ a l, foldl f a l = foldr f a l
id                                   └───┘     └───┘   
src  ─┘                                └───┘        └───┘
typ  ─┘                              └───┘     └───┘   
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘
1400    | a nil      := rfl
id         └─┘         └─┘
src        └─┘         └─┘
typ        └─┘         └─┘
1401    | a (b :: l) :=
id            └┘
src           └┘
typ           └┘
1402      by simp only [foldr_cons, foldl_eq_of_comm_of_assoc hcomm hassoc]; rw (foldl_eq_foldr a l)
id                     └────────┘  └───────────────────────┘ └───┘ └────┘       └────────────┘  
src         └─────────┘└────────┘└┘└───────────────────────┘             └─┘                 └─
typ         └─────────┘└────────┘└┘└───────────────────────┘└───┘└────┘  └─┘ └────────────┘└─
doc         └─────────┘          └┘                                      └─┘                 └─
txt         └─────────┘          └┘                                      └─┘                 └─
par         └─────────┘          └┘                                      └─┘                 └─
pid             └──┘└┘          └┘                                                         
st         └──────────────────────────────────────────────────────────────────┘└───────────────────
1403  
src  
typ  
doc  
txt  
par  
pid  
st   
1404  end foldl_eq_foldr
1405  
1406  section foldl_eq_foldlr'
1407  
1408    variables {f : α → β → α}
1409    variables hf : ∀ a b c, f (f a b) c = f (f a c) b
id                                            
src                                        
typ                                           
1410    include hf
1411  
1412    theorem foldl_eq_of_comm' : ∀ a b l, foldl f a (b::l) = f (foldl f a l) b
id                                       └───┘    └┘     └───┘     
src                                         └───┘       └┘       └───┘
typ                                      └───┘    └┘     └───┘     
1413    | a b [] := rfl
id           └┘    └─┘
src          └┘    └─┘
typ          └┘    └─┘
1414    | a b (c :: l) := by rw [foldl,foldl,foldl,← foldl_eq_of_comm',foldl,hf]
id              └┘              └───┘ └───┘ └───┘   └───────────────┘ └───┘ └┘
src             └┘          └──┘└───┘└───┘└───┘└─┘                 └───┘  └─
typ             └┘          └──┘└───┘└───┘└───┘└─┘└───────────────┘└───┘└┘└─
doc                         └──┘               └─┘                        └─
txt                         └──┘               └─┘                        └─
par                         └──┘               └─┘                        └─
pid                           └┘               └─┘                        
st                         └────────┘└────┘└────┘└──────────────────┘└────┘└─┘
1415  
src  
typ  
doc  
txt  
par  
pid  
st   
1416    theorem foldl_eq_foldr' : ∀ a l, foldl f a l = foldr (flip f) a l
id                                    └───┘     └───┘  └──┘    
src  ─┘                                 └───┘        └───┘  └──┘
typ  ─┘                               └───┘     └───┘  └──┘    
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘
1417    | a [] := rfl
id         └┘    └─┘
src        └┘    └─┘
typ        └┘    └─┘
1418    | a (b :: l) := by rw [foldl_eq_of_comm' hf,foldr,foldl_eq_foldr']; refl
id            └┘              └───────────────┘ └┘ └───┘ └─────────────┘
src           └┘          └──┘└───────────────┘  └───┘                 └────
typ           └┘          └──┘└───────────────┘└┘└───┘└─────────────┘  └────
doc                       └──┘                                         └────
txt                       └──┘                                         └────
par                       └──┘                                         └────
pid                         └┘                                             
st                       └───────────────────────┘└────┘└──────────────┘└──────
1419  
src  
typ  
doc  
txt  
par  
pid  
st   
1420  end foldl_eq_foldlr'
1421  
1422  section foldl_eq_foldlr'
1423  
1424    variables {f : α → β → β}
1425    variables hf : ∀ a b c, f a (f b c) = f b (f a c)
id                                           
src                                        
typ                                          
1426    include hf
1427  
1428    theorem foldr_eq_of_comm' : ∀ a b l, foldr f a (b::l) = foldr f (f b a) l
id                                       └───┘    └┘   └───┘       
src                                         └───┘       └┘    └───┘
typ                                      └───┘    └┘   └───┘       
1429    | a b [] := rfl
id           └┘    └─┘
src          └┘    └─┘
typ          └┘    └─┘
1430    | a b (c :: l) := by rw [foldr,foldr,foldr,hf,← foldr_eq_of_comm']; refl
id              └┘              └───┘ └───┘ └───┘ └┘   └───────────────┘
src             └┘          └──┘└───┘└───┘└───┘  └─┘                   └────
typ             └┘          └──┘└───┘└───┘└───┘└┘└─┘└───────────────┘  └────
doc                         └──┘                 └─┘                   └────
txt                         └──┘                 └─┘                   └────
par                         └──┘                 └─┘                   └────
pid                           └┘                 └─┘                       
st                         └────────┘└────┘└────┘└─┘└──────────────────┘└──────
1431  
src  
typ  
doc  
txt  
par  
pid  
st   
1432  end foldl_eq_foldlr'
1433  
1434  section
1435  variables {op : α → α → α} [ha : is_associative α op] [hc : is_commutative α op]
id                                    └────────────┘             └────────────┘
src                                   └────────────┘             └────────────┘
typ                                   └────────────┘             └────────────┘
1436  local notation a * b := op a b
1437  local notation l <*> a := foldl op a l
id                             └───┘
src                            └───┘
typ                            └───┘
1438  
1439  include ha
1440  
1441  lemma foldl_assoc : ∀ {l : list α} {a₁ a₂}, l <*> (a₁ * a₂) = a₁ * (l <*> a₂)
id                             └──┘    └┘ └┘    └─┘  └┘  └┘   └┘    └─┘ └┘
src                             └──┘               └─┘                    └─┘
typ                            └──┘    └┘ └┘    └─┘  └┘  └┘   └┘    └─┘ └┘
1442  | [] a₁ a₂ := rfl
id     └┘          └─┘
src    └┘          └─┘
typ    └┘          └─┘
1443  | (a :: l) a₁ a₂ :=
id       └┘   └┘ └┘
src       └┘
typ      └┘   └┘ └┘
1444    calc a::l <*> (a₁ * a₂) = l <*> (a₁ * (a₂ * a)) : by simp only [foldl_cons, ha.assoc]
id           └┘  └─┘              └─┘                               └────────┘
src          └┘  └─┘               └─┘                      └─────────┘└────────┘└┘        └─
typ          └┘  └─┘              └─┘                    └─────────┘└────────┘└┘└──────┘└─
doc                                                         └─────────┘          └┘        └─
txt                                                         └─────────┘          └┘        └─
par                                                         └─────────┘          └┘        └─
pid                                                             └──┘└┘          └┘        
st                                                         └─────────────────────────────────
1445      ... = a₁ * (a::l <*> a₂) : by rw [foldl_assoc, foldl_cons]
id                   └┘  └─┘                           └────────┘
src  ───┘             └┘  └─┘          └──┘           └┘└────────┘└─
typ  ───┘            └┘  └─┘          └──┘└─────────┘└┘└────────┘└─
doc  ───┘                              └──┘           └┘          └─
txt  ───┘                              └──┘           └┘          └─
par  ───┘                              └──┘           └┘          └─
pid  ───┘                                └┘           └┘          
st   ───┘                             └──────────────┘└──────────┘
1446  
src  
typ  
doc  
txt  
par  
pid  
st   
1447  lemma foldl_op_eq_op_foldr_assoc : ∀{l : list α} {a₁ a₂}, (l <*> a₁) * a₂ = a₁ * l.foldr (*) a₂
id                                           └──┘    └┘ └┘     └─┘ └┘   └┘  └┘  └────┘    └┘
src                                           └──┘                └─┘                 └────┘
typ                                          └──┘    └┘ └┘     └─┘ └┘   └┘  └┘  └────┘    └┘
1448  | [] a₁ a₂ := rfl
id     └┘          └─┘
src    └┘          └─┘
typ    └┘          └─┘
1449  | (a :: l) a₁ a₂ := by simp only [foldl_cons, foldr_cons, foldl_assoc, ha.assoc]; rw [foldl_op_eq_op_foldr_assoc]
id        └┘                           └────────┘  └────────┘  └─────────┘
src       └┘                └─────────┘└────────┘└┘└────────┘└┘└─────────┘└┘          └──┘                          └─
typ       └┘                └─────────┘└────────┘└┘└────────┘└┘└─────────┘└┘└──────┘  └──┘└────────────────────────┘└─
doc                         └─────────┘          └┘          └┘           └┘          └──┘                          └─
txt                         └─────────┘          └┘          └┘           └┘          └──┘                          └─
par                         └─────────┘          └┘          └┘           └┘          └──┘                          └─
pid                             └──┘└┘          └┘          └┘           └┘            └┘                          
st                         └──────────────────────────────────────────────────────────────┘└────────────────────────┘
1450  
src  
typ  
doc  
txt  
par  
pid  
st   
1451  include hc
1452  
1453  lemma foldl_assoc_comm_cons {l : list α} {a₁ a₂} : (a₁ :: l) <*> a₂ = a₁ * (l <*> a₂) :=
id                                    └──┘              └┘ └┘   └─┘ └┘  └┘    └─┘ └┘
src                                   └──┘                  └┘    └─┘             └─┘
typ                                   └──┘              └┘ └┘   └─┘ └┘  └┘    └─┘ └┘
1454  by rw [foldl_cons, hc.comm, foldl_assoc]
id          └────────┘           └─────────┘
src     └──┘└────────┘└┘       └┘└─────────┘└─
typ     └──┘└────────┘└┘└─────┘└┘└─────────┘└─
doc     └──┘          └┘       └┘           └─
txt     └──┘          └┘       └┘           └─
par     └──┘          └┘       └┘           └─
pid       └┘          └┘       └┘           
st     └─────────────┘└───────┘└───────────┘
1455  
src  
typ  
doc  
txt  
par  
pid  
st   
1456  end
1457  
1458  /- mfoldl, mfoldr -/
1459  
1460  section mfoldl_mfoldr
1461  variables {m : Type v → Type w} [monad m]
id                  └──┘              └───┘
src                                   └───┘
typ                 └──┘              └───┘
1462  
1463  @[simp] theorem mfoldl_nil (f : β → α → m β) {b} : mfoldl f b [] = pure b := rfl
id                                                  └────┘   └┘  └──┘     └─┘
src                                                     └────┘     └┘  └──┘      └─┘
typ                                                 └────┘   └┘  └──┘     └─┘
doc    └──┘
1464  
1465  @[simp] theorem mfoldr_nil (f : α → β → m β) {b} : mfoldr f b [] = pure b := rfl
id                                                  └────┘   └┘  └──┘     └─┘
src                                                     └────┘     └┘  └──┘      └─┘
typ                                                 └────┘   └┘  └──┘     └─┘
doc    └──┘
1466  
1467  @[simp] theorem mfoldl_cons {f : β → α → m β} {b a l} :
id                                           
typ                                          
doc    └──┘
1468    mfoldl f b (a :: l) = f b a >>= λ b', mfoldl f b' l := rfl
id     └────┘     └┘       └─┘   └┘  └────┘  └┘     └─┘
src    └────┘        └┘           └─┘       └────┘           └─┘
typ    └────┘     └┘       └─┘   └┘  └────┘  └┘     └─┘
1469  
1470  @[simp] theorem mfoldr_cons {f : α → β → m β} {b a l} :
id                                           
typ                                          
doc    └──┘
1471    mfoldr f b (a :: l) = mfoldr f b l >>= f a := rfl
id     └────┘     └┘    └────┘    └─┘      └─┘
src    └────┘        └┘     └────┘       └─┘        └─┘
typ    └────┘     └┘    └────┘    └─┘      └─┘
1472  
1473  variables [is_lawful_monad m]
id              └─────────────┘
src             └─────────────┘
typ             └─────────────┘
1474  
1475  @[simp] theorem mfoldl_append {f : β → α → m β} : ∀ {b l₁ l₂},
id                                                    └┘ └┘
typ                                                   └┘ └┘
doc    └──┘
1476    mfoldl f b (l₁ ++ l₂) = mfoldl f b l₁ >>= λ x, mfoldl f x l₂
id     └────┘    └┘ └┘ └┘   └────┘   └┘ └─┘     └────┘   └┘
src    └────┘         └┘      └────┘        └─┘      └────┘
typ    └────┘    └┘ └┘ └┘   └────┘   └┘ └─┘     └────┘   └┘
1477  | _ []     _ := by simp only [nil_append, mfoldl_nil, pure_bind]
id       └┘                        └────────┘  └────────┘  └───────┘
src      └┘             └─────────┘└────────┘└┘└────────┘└┘└───────┘└┘
typ      └┘             └─────────┘└────────┘└┘└────────┘└┘└───────┘└┘
doc                     └─────────┘          └┘          └┘         └┘
txt                     └─────────┘          └┘          └┘         └┘
par                     └─────────┘          └┘          └┘         └┘
pid                         └──┘└┘          └┘          └┘         
st                     └─────────────────────────────────────────────┘
1478  | _ (_::_) _ := by simp only [cons_append, mfoldl_cons, mfoldl_append, bind_assoc]
id         └┘                      └─────────┘  └─────────┘                 └────────┘
src        └┘           └─────────┘└─────────┘└┘└─────────┘└┘             └┘└────────┘└─
typ        └┘           └─────────┘└─────────┘└┘└─────────┘└┘└───────────┘└┘└────────┘└─
doc                     └─────────┘           └┘           └┘             └┘          └─
txt                     └─────────┘           └┘           └┘             └┘          └─
par                     └─────────┘           └┘           └┘             └┘          └─
pid                         └──┘└┘           └┘           └┘             └┘          
st                     └────────────────────────────────────────────────────────────────
1479  
src  
typ  
doc  
txt  
par  
pid  
st   
1480  @[simp] theorem mfoldr_append {f : α → β → m β} : ∀ {b l₁ l₂},
id                                                    └┘ └┘
typ                                                   └┘ └┘
doc    └──┘
1481    mfoldr f b (l₁ ++ l₂) = mfoldr f b l₂ >>= λ x, mfoldr f x l₁
id     └────┘    └┘ └┘ └┘   └────┘   └┘ └─┘     └────┘   └┘
src    └────┘         └┘      └────┘        └─┘      └────┘
typ    └────┘    └┘ └┘ └┘   └────┘   └┘ └─┘     └────┘   └┘
1482  | _ []     _ := by simp only [nil_append, mfoldr_nil, bind_pure]
id       └┘                        └────────┘  └────────┘  └───────┘
src      └┘             └─────────┘└────────┘└┘└────────┘└┘└───────┘└┘
typ      └┘             └─────────┘└────────┘└┘└────────┘└┘└───────┘└┘
doc                     └─────────┘          └┘          └┘         └┘
txt                     └─────────┘          └┘          └┘         └┘
par                     └─────────┘          └┘          └┘         └┘
pid                         └──┘└┘          └┘          └┘         
st                     └─────────────────────────────────────────────┘
1483  | _ (_::_) _ := by simp only [mfoldr_cons, cons_append, mfoldr_append, bind_assoc]
id         └┘                      └─────────┘  └─────────┘                 └────────┘
src        └┘           └─────────┘└─────────┘└┘└─────────┘└┘             └┘└────────┘└─
typ        └┘           └─────────┘└─────────┘└┘└─────────┘└┘└───────────┘└┘└────────┘└─
doc                     └─────────┘           └┘           └┘             └┘          └─
txt                     └─────────┘           └┘           └┘             └┘          └─
par                     └─────────┘           └┘           └┘             └┘          └─
pid                         └──┘└┘           └┘           └┘             └┘          
st                     └────────────────────────────────────────────────────────────────
1484  
src  
typ  
doc  
txt  
par  
pid  
st   
1485  end mfoldl_mfoldr
1486  
1487  /- prod and sum -/
1488  
1489  -- list.sum was already defined in defs.lean, but we couldn't tag it with `to_additive` yet.
1490  attribute [to_additive] list.prod
id                           └───────┘
src                          └───────┘
typ                          └───────┘
doc             └─────────┘  └───────┘
1491  
1492  section monoid
1493  variables [monoid α] {l l₁ l₂ : list α} {a : α}
id              └────┘               └──┘
src             └────┘               └──┘
typ             └────┘               └──┘
1494  
1495  @[simp, to_additive]
doc    └──┘  └─────────┘
1496  theorem prod_nil : ([] : list α).prod = 1 := rfl
id                       └┘   └──┘  └──┘        └─┘
src                      └┘   └──┘   └──┘        └─┘
typ                      └┘   └──┘  └──┘        └─┘
doc                                  └──┘
1497  
1498  @[simp, to_additive]
doc    └──┘  └─────────┘
1499  theorem prod_cons : (a::l).prod = a * l.prod :=
id                        └┘ └──┘     └───┘
src                        └┘  └──┘       └───┘
typ                       └┘ └──┘     └───┘
doc                            └──┘         └───┘
1500  calc (a::l).prod = foldl (*) (a * 1) l : by simp only [list.prod, foldl_cons, one_mul, mul_one]
id         └┘ └──┘    └───┘                           └───────┘  └────────┘  └─────┘  └─────┘
src         └┘  └──┘    └───┘                  └─────────┘└───────┘└┘└────────┘└┘└─────┘└┘└─────┘└─
typ        └┘ └──┘    └───┘                └─────────┘└───────┘└┘└────────┘└┘└─────┘└┘└─────┘└─
doc             └──┘                             └─────────┘└───────┘└┘          └┘       └┘       └─
txt                                              └─────────┘         └┘          └┘       └┘       └─
par                                              └─────────┘         └┘          └┘       └┘       └─
pid                                                  └──┘└┘         └┘          └┘       └┘       
st                                              └────────────────────────────────────────────────────
1501    ... = _ : foldl_assoc
id               └─────────┘
src  ─┘          └─────────┘
typ  ─┘          └─────────┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘
1502  
1503  @[simp, to_additive]
doc    └──┘  └─────────┘
1504  theorem prod_append : (l₁ ++ l₂).prod = l₁.prod * l₂.prod :=
id                          └┘ └┘ └┘ └──┘   └┘└───┘  └┘└───┘
src                            └┘    └──┘     └───┘    └───┘
typ                         └┘ └┘ └┘ └──┘   └┘└───┘  └┘└───┘
doc                                  └──┘      └───┘     └───┘
1505  calc (l₁ ++ l₂).prod = foldl (*) (foldl (*) 1 l₁ * 1) l₂ : by simp [list.prod]
id         └┘ └┘ └┘ └──┘    └───┘     └───┘      └┘     └┘            └───────┘
src           └┘    └──┘    └───┘     └───┘                     └────┘└───────┘└─
typ        └┘ └┘ └┘ └──┘    └───┘     └───┘      └┘     └┘      └────┘└───────┘└─
doc                 └──┘                                           └────┘└───────┘└─
txt                                                                └────┘         └─
par                                                                └────┘         └─
pid                                                                             
st                                                                └─────────────────
1506    ... = l₁.prod * l₂.prod : foldl_assoc
id           └┘└───┘  └┘└───┘   └─────────┘
src  ─┘        └───┘    └───┘   └─────────┘
typ  ─┘      └┘└───┘  └┘└───┘   └─────────┘
doc  ─┘        └───┘     └───┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘
1507  
1508  @[simp, to_additive]
doc    └──┘  └─────────┘
1509  theorem prod_join {l : list (list α)} : l.join.prod = (l.map list.prod).prod :=
id                          └──┘  └──┘      └───┘└───┘   └──┘ └───────┘ └──┘
src                         └──┘  └──┘        └───┘└───┘    └──┘ └───────┘ └──┘
typ                         └──┘  └──┘      └───┘└───┘   └──┘ └───────┘ └──┘
doc                                                └───┘          └───────┘ └──┘
1510  by induction l; [refl, simp only [*, list.join, map, prod_append, prod_cons]]
id                                      └───────┘  └─┘  └─────────┘  └───────┘
src     └────────┘   └──┘  └────────────┘└───────┘└┘└─┘└┘└─────────┘└┘└───────┘
typ     └────────┘  └──┘  └────────────┘└───────┘└┘└─┘└┘└─────────┘└┘└───────┘
doc     └────────┘    └──┘  └────────────┘         └┘   └┘           └┘         
txt     └────────┘    └──┘  └────────────┘         └┘   └┘           └┘         
par     └────────┘    └──┘  └────────────┘         └┘   └┘           └┘         
pid                            └──┘└───┘         └┘   └┘           └┘         
st     └─────────────────────────────────────────────────────────────────────────┘
1511  
1512  @[to_additive]
doc    └─────────┘
1513  theorem prod_hom_rel {α β γ : Type*} [monoid β] [monoid γ] (l : list α) {r : β → γ → Prop}
id                                         └────┘    └────┘        └──┘           
src                                        └────┘     └────┘         └──┘
typ                                        └────┘    └────┘        └──┘           
1514    {f : α → β} {g : α → γ} (h₁ : r 1 1) (h₂ : ∀⦃a b c⦄, r b c → r (f a * b) (g a * c)) :
id                                                                  
src                                                                                 
typ                                                                 
1515    r (l.map f).prod (l.map g).prod :=
id       └──┘  └──┘   └──┘  └──┘
src        └──┘   └──┘    └──┘   └──┘
typ      └──┘  └──┘   └──┘  └──┘
doc               └──┘           └──┘
1516  list.rec_on l h₁ (λ a l hl, by simp only [map_cons, prod_cons, h₂ hl])
id   └─────────┘  └┘      └┘                └──────┘  └───────┘  └┘ └┘
src  └─────────┘                    └─────────┘└──────┘└┘└───────┘└┘    
typ  └─────────┘  └┘      └┘     └─────────┘└──────┘└┘└───────┘└┘└┘└┘
doc                                 └─────────┘        └┘         └┘    
txt                                 └─────────┘        └┘         └┘    
par                                 └─────────┘        └┘         └┘    
pid                                     └──┘└┘        └┘         └┘    
st                                 └─────────────────────────────────────┘
1517  
1518  @[to_additive]
doc    └─────────┘
1519  theorem prod_hom [monoid β] (l : list α) (f : α → β) [is_monoid_hom f] :
id                     └────┘        └──┘              └───────────┘ 
src                    └────┘         └──┘                 └───────────┘
typ                    └────┘        └──┘              └───────────┘ 
doc                                                        └───────────┘
1520    (l.map f).prod = f l.prod :=
id      └──┘  └──┘    └───┘
src      └──┘   └──┘      └───┘
typ     └──┘  └──┘    └───┘
doc             └──┘       └───┘
1521  by { simp only [prod, foldl_map, (is_monoid_hom.map_one f).symm],
id                   └──┘  └───────┘   └───────────────────┘ 
src       └─────────┘└──┘└┘└───────┘└┘ └───────────────────┘ └─────┘
typ       └─────────┘└──┘└┘└───────┘└┘ └───────────────────┘└─────┘
doc       └─────────┘└──┘└┘         └┘                       └─────┘
txt       └─────────┘    └┘         └┘                       └─────┘
par       └─────────┘    └┘         └┘                       └─────┘
pid           └──┘└┘    └┘         └┘                       └─────┘
st     └────────────────────────────────────────────────────────────┘└─
1522    exact l.foldl_hom _ _ _ 1 (is_monoid_hom.map_mul f) }
id           └─────────┘          └───────────────────┘ 
src    └────┘└─────────┘└───────┘ └───────────────────┘ └┘
typ    └────┘└─────────┘└───────┘ └───────────────────┘└┘
doc    └────┘           └───────┘ └───────────────────┘ └┘
txt    └────┘           └───────┘                       └┘
par    └────┘           └───────┘                       └┘
pid                    └───────┘                       
st   ─────────────────────────────────────────────────────┘└┘
1523  
1524  end monoid
1525  
1526  @[simp, to_additive]
doc    └──┘  └─────────┘
1527  theorem prod_erase [decidable_eq α] [comm_monoid α] {a} :
id                       └──────────┘    └─────────┘ 
src                      └──────────┘     └─────────┘
typ                      └──────────┘    └─────────┘ 
1528    Π {l : list α}, a ∈ l → a * (l.erase a).prod = l.prod
id           └──┘            └────┘  └──┘   └───┘
src           └──┘                 └────┘   └──┘    └───┘
typ          └──┘            └────┘  └──┘   └───┘
doc                                           └──┘     └───┘
1529  | (b::l) h :=
id       └┘
src      └┘
typ      └┘
1530    begin
st     └─────
1531      rcases eq_or_ne_mem_of_mem h with rfl | ⟨ne, h⟩,
id              └─────────────────┘ 
src      └─────┘└─────────────────┘ └─────────────────┘
typ      └─────┘└─────────────────┘└─────────────────┘
doc      └─────┘                    └─────────────────┘
txt      └─────┘                    └─────────────────┘
par      └─────┘                    └─────────────────┘
pid                                └─────────────────┘
st   ──────────────────────────────────────────────────┘└─
1532      { simp only [list.erase, if_pos, prod_cons] },
id                    └────────┘  └────┘  └───────┘
src        └─────────┘└────────┘└┘└────┘└┘└───────┘└┘
typ        └─────────┘└────────┘└┘└────┘└┘└───────┘└┘
doc        └─────────┘          └┘      └┘         └┘
txt        └─────────┘          └┘      └┘         └┘
par        └─────────┘          └┘      └┘         └┘
pid            └──┘└┘          └┘      └┘         
st   ─────┘└────────────────────────────────────────┘└┘
1533      { simp only [list.erase, if_neg (mt eq.symm ne), prod_cons, prod_erase h, mul_left_comm a b] }
id                    └────────┘  └────┘  └┘ └─────┘ └┘   └───────┘  └────────┘   └───────────┘  
src        └─────────┘└────────┘└┘└────┘ └┘└─────┘└┘└─┘└───────┘└┘           └┘└───────────┘  └┘
typ        └─────────┘└────────┘└┘└────┘ └┘└─────┘└┘└─┘└───────┘└┘└────────┘└┘└───────────┘└┘
doc        └─────────┘          └┘                  └─┘         └┘           └┘               └┘
txt        └─────────┘          └┘                  └─┘         └┘           └┘               └┘
par        └─────────┘          └┘                  └─┘         └┘           └┘               └┘
pid            └──┘└┘          └┘                  └─┘         └┘           └┘               
st   ────────────────────────────────────────────────────────────────────────────────────────────────┘└─
1534    end
st   ────┘
1535  
1536  lemma dvd_prod [comm_semiring α] {a} {l : list α} (ha : a ∈ l) : a ∣ l.prod :=
id                   └───────────┘            └──┘                 └───┘
src                  └───────────┘             └──┘                      └───┘
typ                  └───────────┘            └──┘                 └───┘
doc                                                                        └───┘
1537  let ⟨s, t, h⟩ := mem_split ha in
id   └─┘              └───────┘ └┘
src                   └───────┘
typ  └─┘              └───────┘ └┘
1538  by rw [h, prod_append, prod_cons, mul_left_comm]; exact dvd_mul_right _ _
id            └─────────┘  └───────┘  └───────────┘         └───────────┘
src     └──┘ └┘└─────────┘└┘└───────┘└┘└───────────┘  └────┘└───────────┘└────
typ     └──┘└┘└─────────┘└┘└───────┘└┘└───────────┘  └────┘└───────────┘└────
doc     └──┘ └┘           └┘         └┘               └────┘             └────
txt     └──┘ └┘           └┘         └┘               └────┘             └────
par     └──┘ └┘           └┘         └┘               └────┘             └────
pid       └┘ └┘           └┘         └┘                                 └──┘
st     └────┘└───────────┘└─────────┘└─────────────┘└─────────────────────────
1539  
src  
typ  
doc  
txt  
par  
pid  
st   
1540  @[simp] theorem sum_const_nat (m n : ℕ) : sum (list.repeat m n) = m * n :=
id                                            └─┘  └─────────┘       
src                                           └─┘  └─────────┘         
typ                                           └─┘  └─────────┘       
doc    └──┘                                    └─┘
1541  by induction n; [refl, simp only [*, repeat_succ, sum_cons, nat.mul_succ, add_comm]]
id                                      └─────────┘  └──────┘  └──────────┘  └──────┘
src     └────────┘   └──┘  └────────────┘└─────────┘└┘└──────┘└┘└──────────┘└┘└──────┘
typ     └────────┘  └──┘  └────────────┘└─────────┘└┘└──────┘└┘└──────────┘└┘└──────┘
doc     └────────┘    └──┘  └────────────┘           └┘        └┘            └┘        
txt     └────────┘    └──┘  └────────────┘           └┘        └┘            └┘        
par     └────────┘    └──┘  └────────────┘           └┘        └┘            └┘        
pid                            └──┘└───┘           └┘        └┘            └┘        
st     └────────────────────────────────────────────────────────────────────────────────┘
1542  
1543  theorem dvd_sum [comm_semiring α] {a} {l : list α} (h : ∀ x ∈ l, a ∣ x) : a ∣ l.sum :=
id                    └───────────┘            └──┘                       └──┘
src                   └───────────┘             └──┘                              └──┘
typ                   └───────────┘            └──┘                       └──┘
doc                                                                                 └──┘
1544  begin
st   └─────
1545    induction l with x l ih,
id               
src    └────────┘ └──────────┘
typ    └────────┘└──────────┘
doc    └────────┘ └──────────┘
txt    └────────┘ └──────────┘
par    └────────┘ └──────────┘
pid              └─────────┘
st   ────────────────────────┘└─
1546    { exact dvd_zero _ },
id             └──────┘
src      └────┘└──────┘└─┘
typ      └────┘└──────┘└─┘
doc      └────┘        └─┘
txt      └────┘        └─┘
par      └────┘        └─┘
pid                   └┘
st   ───┘└───────────────┘└┘
1547    { rw [list.sum_cons],
id           └───────────┘
src      └──┘└───────────┘
typ      └──┘└───────────┘
doc      └──┘             
txt      └──┘             
par      └──┘             
pid        └┘             
st   ────────────────────┘└─
1548      exact dvd_add (h _ (mem_cons_self _ _)) (ih (λ x hx, h x (mem_cons_of_mem _ hx))) }
id             └─────┘       └───────────┘        └┘              └─────────────┘
src      └────┘└─────┘  └─┘ └───────────┘└─────┘     └─────┘   └─────────────┘└─┘  └──┘
typ      └────┘└─────┘  └─┘ └───────────┘└─────┘ └┘  └─────┘  └─────────────┘└─┘  └──┘
doc      └────┘         └─┘              └─────┘     └─────┘                  └─┘  └──┘
txt      └────┘         └─┘              └─────┘     └─────┘                  └─┘  └──┘
par      └────┘         └─┘              └─────┘     └─────┘                  └─┘  └──┘
pid                    └─┘              └─────┘     └─────┘                  └─┘  └─┘
st   ─────────────────────────────────────────────────────────────────────────────────────┘└─
1549  end
st   ──┘
1550  
1551  @[simp] theorem length_join (L : list (list α)) : length (join L) = sum (map length L) :=
id                                    └──┘  └──┘      └────┘  └──┘    └─┘  └─┘ └────┘ 
src                                   └──┘  └──┘       └────┘  └──┘     └─┘  └─┘ └────┘
typ                                   └──┘  └──┘      └────┘  └──┘    └─┘  └─┘ └────┘ 
doc    └──┘                                                              └─┘
1552  by induction L; [refl, simp only [*, join, map, sum_cons, length_append]]
id                                      └──┘  └─┘  └──────┘  └───────────┘
src     └────────┘   └──┘  └────────────┘└──┘└┘└─┘└┘└──────┘└┘└───────────┘
typ     └────────┘  └──┘  └────────────┘└──┘└┘└─┘└┘└──────┘└┘└───────────┘
doc     └────────┘    └──┘  └────────────┘    └┘   └┘        └┘             
txt     └────────┘    └──┘  └────────────┘    └┘   └┘        └┘             
par     └────────┘    └──┘  └────────────┘    └┘   └┘        └┘             
pid                            └──┘└───┘    └┘   └┘        └┘             
st     └─────────────────────────────────────────────────────────────────────┘
1553  
1554  @[simp] theorem length_bind (l : list α) (f : α → list β) : length (list.bind l f) = sum (map (length ∘ f) l) :=
id                                    └──┘           └──┘     └────┘  └───────┘     └─┘  └─┘  └────┘    
src                                   └──┘             └──┘      └────┘  └───────┘       └─┘  └─┘  └────┘ 
typ                                   └──┘           └──┘     └────┘  └───────┘     └─┘  └─┘  └────┘    
doc    └──┘                                                                               └─┘
1555  by rw [list.bind, length_join, map_map]
id          └───────┘  └─────────┘  └─────┘
src     └──┘└───────┘└┘└─────────┘└┘└─────┘└─
typ     └──┘└───────┘└┘└─────────┘└┘└─────┘└─
doc     └──┘         └┘           └┘       └─
txt     └──┘         └┘           └┘       └─
par     └──┘         └┘           └┘       └─
pid       └┘         └┘           └┘       
st     └────────────┘└───────────┘└───────┘
1556  
src  
typ  
doc  
txt  
par  
pid  
st   
1557  lemma exists_lt_of_sum_lt [decidable_linear_ordered_cancel_comm_monoid β] {l : list α}
id                              └─────────────────────────────────────────┘        └──┘ 
src                             └─────────────────────────────────────────┘         └──┘
typ                             └─────────────────────────────────────────┘        └──┘ 
1558    (f g : α → β) (h : (l.map f).sum < (l.map g).sum) : ∃ x ∈ l, f x < g x :=
id                       └──┘  └─┘    └──┘  └─┘              
src                         └──┘   └─┘     └──┘   └─┘                
typ                      └──┘  └─┘    └──┘  └─┘              
doc                                └─┘             └─┘
1559  begin
st   └─────
1560    induction l with x l,
id               
src    └────────┘ └───────┘
typ    └────────┘└───────┘
doc    └────────┘ └───────┘
txt    └────────┘ └───────┘
par    └────────┘ └───────┘
pid              └──────┘
st   ─────────────────────┘└─
1561    { exfalso, exact lt_irrefl _ h },
id                      └───────┘   
src      └─────┘  └────┘└───────┘└─┘ 
typ      └─────┘  └────┘└───────┘└─┘
doc      └─────┘  └────┘         └─┘ 
txt      └─────┘  └────┘         └─┘ 
par      └─────┘  └────┘         └─┘ 
pid                             └─┘ 
st   ───┘└─────┘└────────────────────┘└┘
1562    { by_cases h' : f x < g x, exact ⟨x, mem_cons_self _ _, h'⟩,
id                                     └───────────┘      └┘
src      └───────┘  └─┘      └────┘  └┘└───────────┘└────┘  
typ      └───────┘  └─┘   └────┘ └┘└───────────┘└────┘└┘
doc      └───────┘  └─┘       └────┘  └┘             └────┘  
txt      └───────┘  └─┘       └────┘  └┘             └────┘  
par      └───────┘  └─┘       └────┘  └┘             └────┘  
pid                └─┘              └┘             └────┘  
st   ──────────────────────────┘└────────────────────────────────┘└─
1563      rcases l_ih _ with ⟨y, h1y, h2y⟩, refine ⟨y, mem_cons_of_mem x h1y, h2y⟩, simp at h,
id              └──┘                                 └─────────────┘  └─┘  └─┘
src      └─────┘    └───────────────────┘  └─────┘  └┘└─────────────┘    └┘     └───────┘
typ      └─────┘└──┘└───────────────────┘  └─────┘ └┘└─────────────┘└─┘└┘└─┘  └───────┘
doc      └─────┘    └───────────────────┘  └─────┘  └┘                   └┘     └───────┘
txt      └─────┘    └───────────────────┘  └─────┘  └┘                   └┘     └───────┘
par      └─────┘    └───────────────────┘  └─────┘  └┘                   └┘     └───────┘
pid                └───────────────────┘          └┘                   └┘         └──┘
st   ───────────────────────────────────┘└──────────────────────────────────────┘└─────────┘└─
1564      exact lt_of_add_lt_add_left' (lt_of_lt_of_le h $ add_le_add_right (le_of_not_gt h') _) }
id             └────────────────────┘  └────────────┘    └──────────────┘  └──────────┘ └┘
src      └────┘└────────────────────┘ └────────────┘  └──────────────┘ └──────────┘  └───┘
typ      └────┘└────────────────────┘ └────────────┘ └──────────────┘ └──────────┘└┘└───┘
doc      └────┘                                                                      └───┘
txt      └────┘                                                                      └───┘
par      └────┘                                                                      └───┘
pid                                                                                 └──┘
st   ──────────────────────────────────────────────────────────────────────────────────────────┘└─
1565  end
st   ──┘
1566  
1567  lemma exists_le_of_sum_le [decidable_linear_ordered_cancel_comm_monoid β] {l : list α}
id                              └─────────────────────────────────────────┘        └──┘ 
src                             └─────────────────────────────────────────┘         └──┘
typ                             └─────────────────────────────────────────┘        └──┘ 
1568    (hl : l ≠ []) (f g : α → β) (h : (l.map f).sum ≤ (l.map g).sum) : ∃ x ∈ l, f x ≤ g x :=
id             └┘                    └──┘  └─┘    └──┘  └─┘              
src             └┘                       └──┘   └─┘     └──┘   └─┘                
typ            └┘                    └──┘  └─┘    └──┘  └─┘              
doc                                              └─┘             └─┘
1569  begin
st   └─────
1570    cases l with x l,
id           
src    └────┘ └───────┘
typ    └────┘└───────┘
doc    └────┘ └───────┘
txt    └────┘ └───────┘
par    └────┘ └───────┘
pid          └───────┘
st   ─────────────────┘└─
1571    { contradiction },
src      └────────────┘
typ      └────────────┘
doc      └────────────┘
txt      └────────────┘
par      └────────────┘
pid                   
st   ───┘└────────────┘└┘
1572    { by_cases h' : f x ≤ g x, exact ⟨x, mem_cons_self _ _, h'⟩,
id                                     └───────────┘      └┘
src      └───────┘  └─┘      └────┘  └┘└───────────┘└────┘  
typ      └───────┘  └─┘   └────┘ └┘└───────────┘└────┘└┘
doc      └───────┘  └─┘       └────┘  └┘             └────┘  
txt      └───────┘  └─┘       └────┘  └┘             └────┘  
par      └───────┘  └─┘       └────┘  └┘             └────┘  
pid                └─┘              └┘             └────┘  
st   ──────────────────────────┘└────────────────────────────────┘└─
1573      rcases exists_lt_of_sum_lt f g _ with ⟨y, h1y, h2y⟩,
id              └─────────────────┘  
src      └─────┘└─────────────────┘  └───────────────────┘
typ      └─────┘└─────────────────┘└───────────────────┘
doc      └─────┘                     └───────────────────┘
txt      └─────┘                     └───────────────────┘
par      └─────┘                     └───────────────────┘
pid                                 └───────────────────┘
st   ──────────────────────────────────────────────────────┘└─
1574      exact ⟨y, mem_cons_of_mem x h1y, le_of_lt h2y⟩, simp at h,
id                └─────────────┘  └─┘  └──────┘ └─┘
src      └────┘  └┘└─────────────┘    └┘└──────┘     └───────┘
typ      └────┘ └┘└─────────────┘└─┘└┘└──────┘└─┘  └───────┘
doc      └────┘  └┘                   └┘             └───────┘
txt      └────┘  └┘                   └┘             └───────┘
par      └────┘  └┘                   └┘             └───────┘
pid             └┘                   └┘                 └──┘
st   ─────────────────────────────────────────────────┘└─────────┘└─
1575      exact lt_of_add_lt_add_left' (lt_of_le_of_lt h $ add_lt_add_right (lt_of_not_ge h') _) }
id             └────────────────────┘  └────────────┘    └──────────────┘  └──────────┘ └┘
src      └────┘└────────────────────┘ └────────────┘  └──────────────┘ └──────────┘  └───┘
typ      └────┘└────────────────────┘ └────────────┘ └──────────────┘ └──────────┘└┘└───┘
doc      └────┘                                                                      └───┘
txt      └────┘                                                                      └───┘
par      └────┘                                                                      └───┘
pid                                                                                 └──┘
st   ──────────────────────────────────────────────────────────────────────────────────────────┘└─
1576  end
st   ──┘
1577  
1578  /- lexicographic ordering -/
1579  
1580  inductive lex (r : α → α → Prop) : list α → list α → Prop
id                                    └──┘     └──┘
src                                     └──┘     └──┘
typ                                   └──┘     └──┘
1581  | nil {} {a l} : lex [] (a :: l)
id                      └┘   └┘ 
src                       └┘    └┘
typ                     └┘   └┘ 
1582  | cons {a l₁ l₂} (h : lex l₁ l₂) : lex (a :: l₁) (a :: l₂)
id            └┘ └┘       └─┘ └┘ └┘          └┘ └┘    └┘ └┘
src                                            └┘        └┘
typ           └┘ └┘       └─┘ └┘ └┘          └┘ └┘    └┘ └┘
1583  | rel {a₁ l₁ a₂ l₂} (h : r a₁ a₂) : lex (a₁ :: l₁) (a₂ :: l₂)
id          └┘ └┘ └┘ └┘        └┘ └┘         └┘ └┘ └┘   └┘ └┘ └┘
src                                              └┘         └┘
typ         └┘ └┘ └┘ └┘        └┘ └┘         └┘ └┘ └┘   └┘ └┘ └┘
1584  
1585  namespace lex
1586  theorem cons_iff {r : α → α → Prop} [is_irrefl α r] {a l₁ l₂} :
id                                      └───────┘  
src                                       └───────┘
typ                                     └───────┘  
1587    lex r (a :: l₁) (a :: l₂) ↔ lex r l₁ l₂ :=
id     └─┘    └┘ └┘    └┘ └┘   └─┘  └┘ └┘
src    └─┘      └┘        └┘      └─┘
typ    └─┘    └┘ └┘    └┘ └┘   └─┘  └┘ └┘
1588  ⟨λ h, by cases h with _ _ _ _ _ h _ _ _ _ h;
id                 
src           └────┘ └─────────────────────────┘
typ          └────┘└─────────────────────────┘
doc           └────┘ └─────────────────────────┘
txt           └────┘ └─────────────────────────┘
par           └────┘ └─────────────────────────┘
pid                 └─────────────────────────┘
st           └────────────────────────────────────
1589    [exact h, exact (irrefl_of r a h).elim], lex.cons⟩
id                    └───────┘            └──────┘
src    └────┘   └────┘ └───────┘   └────┘   └──────┘
typ    └────┘  └────┘ └───────┘└────┘   └──────┘
doc     └────┘   └────┘             └────┘
txt     └────┘   └────┘             └────┘
par     └────┘   └────┘             └────┘
pid                               └───┘
st   ────────────────────────────────────────┘
1590    
1591  @[simp] theorem not_nil_right (r : α → α → Prop) (l : list α) : ¬ lex r l [].
id                                                       └──┘      └─┘   └┘
src                                                        └──┘       └─┘     └┘
typ                                                      └──┘      └─┘   └┘
doc    └──┘
1592  
1593  instance is_order_connected (r : α → α → Prop)
id                                       
typ                                      
1594    [is_order_connected α r] [is_trichotomous α r] :
id      └────────────────┘     └─────────────┘  
src     └────────────────┘       └─────────────┘
typ     └────────────────┘     └─────────────┘  
doc     └────────────────┘
1595    is_order_connected (list α) (lex r) :=
id     └────────────────┘  └──┘    └─┘ 
src    └────────────────┘  └──┘     └─┘
typ    └────────────────┘  └──┘    └─┘ 
doc    └────────────────┘
1596  ⟨λ l₁, match l₁ with
id      └┘        └┘
typ     └┘        └┘
1597  | _,     [],    c::l₃, nil    := or.inr nil
id            └┘      └┘    └─┘       └────┘ └─┘
src           └┘      └┘    └─┘       └────┘ └─┘
typ           └┘      └┘    └─┘       └────┘ └─┘
1598  | _,     [],    c::l₃, rel _ := or.inr nil
id            └┘      └┘    └─┘      └────┘ └─┘
src           └┘      └┘    └─┘      └────┘ └─┘
typ           └┘      └┘    └─┘      └────┘ └─┘
1599  | _,     [],    c::l₃, cons _ := or.inr nil
id            └┘      └┘    └──┘      └────┘ └─┘
src           └┘      └┘    └──┘      └────┘ └─┘
typ           └┘      └┘    └──┘      └────┘ └─┘
1600  | _,     b::l₂, c::l₃, nil := or.inl nil
id             └┘     └┘    └─┘    └────┘ └─┘
src            └┘     └┘    └─┘    └────┘ └─┘
typ            └┘     └┘    └─┘    └────┘ └─┘
1601  | a::l₁, b::l₂, c::l₃, rel h :=
id      └┘    └┘     └┘    └─┘ 
src     └┘     └┘     └┘    └─┘
typ     └┘    └┘     └┘    └─┘ 
1602    (is_order_connected.conn _ b _ h).imp rel rel
id      └─────────────────────┘         └─┘  └─┘ └─┘
src     └─────────────────────┘         └─┘  └─┘ └─┘
typ     └─────────────────────┘         └─┘  └─┘ └─┘
1603  | a::l₁, b::l₂, _::l₃, cons h := begin
id      └┘     └┘     └┘    └──┘
src     └┘     └┘     └┘    └──┘
typ     └┘     └┘     └┘    └──┘
st                                    └─────
1604      rcases trichotomous_of r a b with ab | rfl | ab,
id              └─────────────┘   
src      └─────┘└─────────────┘   └─────────────────┘
typ      └─────┘└─────────────┘└─────────────────┘
doc      └─────┘                  └─────────────────┘
txt      └─────┘                  └─────────────────┘
par      └─────┘                  └─────────────────┘
pid                              └─────────────────┘
st   ──────────────────────────────────────────────────┘└─
1605      { exact or.inl (rel ab) },
id               └────┘  └─┘ └┘
src        └────┘└────┘ └─┘  └┘
typ        └────┘└────┘ └─┘└┘└┘
doc        └────┘            └┘
txt        └────┘            └┘
par        └────┘            └┘
pid                         
st   ─────┘└────────────────────┘└┘
1606      { exact (_match _ l₂ _ h).imp cons cons },
id                └────┘   └┘              └──┘
src        └────┘       └─┘  └─┘ └────┘    └──┘
typ        └────┘ └────┘└─┘└┘└─┘└────┘    └──┘
doc        └────┘       └─┘  └─┘ └────┘        
txt        └────┘       └─┘  └─┘ └────┘        
par        └────┘       └─┘  └─┘ └────┘        
pid                    └─┘  └─┘ └────┘        
st   ─────┘└────────────────────────────────────┘└┘
1607      { exact or.inr (rel ab) }
id               └────┘  └─┘ └┘
src        └────┘└────┘ └─┘  └┘
typ        └────┘└────┘ └─┘└┘└┘
doc        └────┘            └┘
txt        └────┘            └┘
par        └────┘            └┘
pid                         
st   ───────────────────────────┘└─
1608    end
st   ────┘
1609  end⟩
1610  
1611  instance is_trichotomous (r : α → α → Prop) [is_trichotomous α r] :
id                                              └─────────────┘  
src                                               └─────────────┘
typ                                             └─────────────┘  
1612    is_trichotomous (list α) (lex r) :=
id     └─────────────┘  └──┘    └─┘ 
src    └─────────────┘  └──┘     └─┘
typ    └─────────────┘  └──┘    └─┘ 
1613  ⟨λ l₁, match l₁ with
id      └┘        └┘
typ     └┘        └┘
1614  | [], [] := or.inr (or.inl rfl)
id     └┘  └┘    └────┘  └────┘ └─┘
src    └┘  └┘    └────┘  └────┘ └─┘
typ    └┘  └┘    └────┘  └────┘ └─┘
1615  | [], b::l₂ := or.inl nil
id     └┘   └┘      └────┘ └─┘
src    └┘   └┘      └────┘ └─┘
typ    └┘   └┘      └────┘ └─┘
1616  | a::l₁, [] := or.inr (or.inr nil)
id      └┘    └┘    └────┘  └────┘ └─┘
src     └┘    └┘    └────┘  └────┘ └─┘
typ     └┘    └┘    └────┘  └────┘ └─┘
1617  | a::l₁, b::l₂ := begin
id      └┘     └┘
src     └┘     └┘
typ     └┘     └┘
st                     └─────
1618      rcases trichotomous_of r a b with ab | rfl | ab,
id              └─────────────┘   
src      └─────┘└─────────────┘   └─────────────────┘
typ      └─────┘└─────────────┘└─────────────────┘
doc      └─────┘                  └─────────────────┘
txt      └─────┘                  └─────────────────┘
par      └─────┘                  └─────────────────┘
pid                              └─────────────────┘
st   ──────────────────────────────────────────────────┘└─
1619      { exact or.inl (rel ab) },
id               └────┘  └─┘ └┘
src        └────┘└────┘ └─┘  └┘
typ        └────┘└────┘ └─┘└┘└┘
doc        └────┘            └┘
txt        └────┘            └┘
par        └────┘            └┘
pid                         
st   ─────┘└────────────────────┘└┘
1620      { exact (_match l₁ l₂).imp cons
id                └────┘ └┘ └┘
src        └────┘           └────┘    
typ        └────┘ └────┘└┘└┘└────┘    
doc        └────┘           └────┘    
txt        └────┘           └────┘    
par        └────┘           └────┘    
pid                        └────┘    
st   ─────┘└─────────────────────────────
1621        (or.imp (congr_arg _) cons) },
id          └────┘  └───────┘    └──┘
src  ─────┘ └────┘ └───────┘└──┘└──┘└┘
typ  ─────┘ └────┘ └───────┘└──┘└──┘└┘
doc  ─────┘                 └──┘    └┘
txt  ─────┘                 └──┘    └┘
par  ─────┘                 └──┘    └┘
pid  ─────┘                 └──┘    
st   ─────────────────────────────────┘└┘
1622      { exact or.inr (or.inr (rel ab)) }
id                       └────┘  └─┘ └┘
src        └────┘       └────┘ └─┘  └─┘
typ        └────┘       └────┘ └─┘└┘└─┘
doc        └────┘                   └─┘
txt        └────┘                   └─┘
par        └────┘                   └─┘
pid                                └┘
st   ────────────────────────────────────┘└─
1623    end
st   ────┘
1624  end⟩
1625  
1626  instance is_asymm (r : α → α → Prop)
id                             
typ                            
1627    [is_asymm α r] : is_asymm (list α) (lex r) :=
id      └──────┘      └──────┘  └──┘    └─┘ 
src     └──────┘        └──────┘  └──┘     └─┘
typ     └──────┘      └──────┘  └──┘    └─┘ 
1628  ⟨λ l₁, match l₁ with
id      └┘        └┘
typ     └┘        └┘
1629  | a::l₁, b::l₂, lex.rel h₁, lex.rel h₂ := asymm h₁ h₂
id      └┘     └┘            └┘  └─────┘ └┘    └───┘
src     └┘     └┘                └─────┘       └───┘
typ     └┘     └┘            └┘  └─────┘ └┘    └───┘
1630  | a::l₁, b::l₂, lex.rel h₁, lex.cons h₂ := asymm h₁ h₁
id      └┘     └┘    └─────┘ └┘  └──────┘       └───┘
src     └┘     └┘    └─────┘     └──────┘       └───┘
typ     └┘     └┘    └─────┘ └┘  └──────┘       └───┘
1631  | a::l₁, b::l₂, lex.cons h₁, lex.rel h₂ := asymm h₂ h₂
id      └┘     └┘    └──────┘     └─────┘ └┘    └───┘
src     └┘     └┘    └──────┘     └─────┘       └───┘
typ     └┘     └┘    └──────┘     └─────┘ └┘    └───┘
1632  | a::l₁, b::l₂, lex.cons h₁, lex.cons h₂ :=
id      └┘     └┘                 └──────┘
src     └┘     └┘                 └──────┘
typ     └┘     └┘                 └──────┘
1633    by exact _match _ _ h₁ h₂
id              └────┘     └┘ └┘
src       └────┘      └───┘    
typ       └────┘└────┘└───┘└┘└┘
doc       └────┘      └───┘    
txt       └────┘      └───┘    
par       └────┘      └───┘    
pid                  └───┘    
st       └──────────────────────┘
1634  end⟩
1635  
1636  instance is_strict_total_order (r : α → α → Prop)
id                                          
typ                                         
1637    [is_strict_total_order' α r] : is_strict_total_order' (list α) (lex r) :=
id      └────────────────────┘      └────────────────────┘  └──┘    └─┘ 
src     └────────────────────┘        └────────────────────┘  └──┘     └─┘
typ     └────────────────────┘      └────────────────────┘  └──┘    └─┘ 
doc     └────────────────────┘        └────────────────────┘
1638  {..is_strict_weak_order_of_is_order_connected}
id      └────────────────────────────────────────┘
src     └────────────────────────────────────────┘
typ     └────────────────────────────────────────┘
1639  
1640  instance decidable_rel [decidable_eq α] (r : α → α → Prop)
id                           └──────────┘           
src                          └──────────┘
typ                          └──────────┘           
1641    [decidable_rel r] : decidable_rel (lex r)
id      └───────────┘     └───────────┘  └─┘ 
src     └───────────┘      └───────────┘  └─┘
typ     └───────────┘     └───────────┘  └─┘ 
1642  | l₁ [] := is_false $ λ h, by cases h
id        └┘    └──────┘                
src       └┘    └──────┘           └────┘ 
typ       └┘    └──────┘          └────┘
doc                                └────┘ 
txt                                └────┘ 
par                                └────┘ 
pid                                      
st                                └───────┘
1643  | [] (b::l₂) := is_true lex.nil
id     └┘   └┘       └─────┘ └─────┘
src    └┘   └┘       └─────┘ └─────┘
typ    └┘   └┘       └─────┘ └─────┘
1644  | (a::l₁) (b::l₂) := begin
id       └┘      └┘
src      └┘      └┘
typ      └┘      └┘
st                        └─────
1645    haveI := decidable_rel l₁ l₂,
id              └───────────┘ └┘ └┘
src    └───────┘└───────────┘  
typ    └───────┘└───────────┘└┘└┘
doc    └───────┘               
txt    └───────┘               
par    └───────┘               
pid         └─┘               
st   ─────────────────────────────┘└─
1646    refine decidable_of_iff (r a b ∨ a = b ∧ lex r l₁ l₂) ⟨λ h, _, λ h, _⟩,
id            └──────────────┘             └─┘  └┘ └┘
src    └─────┘└──────────────┘      └─┘     └┘  └─────┘ └────┘
typ    └─────┘└──────────────┘    └─┘└┘└┘└┘  └─────┘ └────┘
doc    └─────┘                                 └┘  └─────┘ └────┘
txt    └─────┘                                 └┘  └─────┘ └────┘
par    └─────┘                                 └┘  └─────┘ └────┘
pid                                           └┘  └─────┘ └────┘
st   ───────────────────────────────────────────────────────────────────────┘└─
1647    { rcases h with h | ⟨rfl, h⟩,
id              
src      └─────┘ └────────────────┘
typ      └─────┘└────────────────┘
doc      └─────┘ └────────────────┘
txt      └─────┘ └────────────────┘
par      └─────┘ └────────────────┘
pid             └────────────────┘
st   ───┘└────────────────────────┘└─
1648      { exact lex.rel h },
id               └─────┘ 
src        └────┘└─────┘ 
typ        └────┘└─────┘
doc        └────┘        
txt        └────┘        
par        └────┘        
pid                     
st   ─────┘└──────────────┘└┘
1649      { exact lex.cons h } },
id               └──────┘ 
src        └────┘└──────┘ 
typ        └────┘└──────┘
doc        └────┘         
txt        └────┘         
par        └────┘         
pid                      
st   ──────────────────────┘└──┘
1650    { rcases h with _|⟨_,_,_,h⟩|⟨_,_,_,_,h⟩,
id              
src      └─────┘ └───────────────────────────┘
typ      └─────┘└───────────────────────────┘
doc      └─────┘ └───────────────────────────┘
txt      └─────┘ └───────────────────────────┘
par      └─────┘ └───────────────────────────┘
pid             └───────────────────────────┘
st   ────────────────────────────────────────┘└─
1651      { exact or.inr ⟨rfl, h⟩ },
id               └────┘  └─┘  
src        └────┘└────┘ └─┘└┘ └┘
typ        └────┘└────┘ └─┘└┘└┘
doc        └────┘          └┘ └┘
txt        └────┘          └┘ └┘
par        └────┘          └┘ └┘
pid                       └┘ 
st   ─────┘└────────────────────┘└┘
1652      { exact or.inl h } }
id               └────┘ 
src        └────┘└────┘ 
typ        └────┘└────┘
doc        └────┘       
txt        └────┘       
par        └────┘       
pid                    
st   ────────────────────┘└───
1653  end
st   ──┘
1654  
1655  theorem append_right (r : α → α → Prop) :
id                                
typ                               
1656    ∀ {s₁ s₂} t, lex r s₁ s₂ → lex r s₁ (s₂ ++ t)
id       └┘ └┘    └─┘  └┘ └┘   └─┘  └┘  └┘ └┘ 
src                 └─┘           └─┘          └┘
typ      └┘ └┘    └─┘  └┘ └┘   └─┘  └┘  └┘ └┘ 
1657  | _ _ t nil      := nil
id           └─┘         └─┘
src          └─┘         └─┘
typ          └─┘         └─┘
1658  | _ _ t (cons h) := cons (append_right _ h)
id            └──┘      └──┘  └──────────┘
src           └──┘       └──┘
typ           └──┘      └──┘  └──────────┘
1659  | _ _ t (rel r)  := rel r
id            └─┘       └─┘
src           └─┘        └─┘
typ           └─┘       └─┘
1660  
1661  theorem append_left (R : α → α → Prop) {t₁ t₂} (h : lex R t₁ t₂) :
id                                                     └─┘  └┘ └┘
src                                                      └─┘
typ                                                    └─┘  └┘ └┘
1662    ∀ s, lex R (s ++ t₁) (s ++ t₂)
id         └─┘    └┘ └┘    └┘ └┘
src         └─┘      └┘        └┘
typ        └─┘    └┘ └┘    └┘ └┘
1663  | []      := h
id     └┘         
src    └┘
typ    └┘         
1664  | (a::l) := cons (append_left l)
id       └┘     └──┘  └─────────┘
src      └┘      └──┘
typ      └┘     └──┘  └─────────┘
1665  
1666  theorem imp {r s : α → α → Prop} (H : ∀ a b, r a b → s a b) :
id                                                   
typ                                                  
1667    ∀ l₁ l₂, lex r l₁ l₂ → lex s l₁ l₂
id       └┘ └┘  └─┘  └┘ └┘   └─┘  └┘ └┘
src             └─┘           └─┘
typ      └┘ └┘  └─┘  └┘ └┘   └─┘  └┘ └┘
1668  | _ _ nil      := nil
id         └─┘         └─┘
src        └─┘         └─┘
typ        └─┘         └─┘
1669  | _ _ (cons h) := cons (imp _ _ h)
id          └──┘      └──┘  └─┘
src         └──┘       └──┘
typ         └──┘      └──┘  └─┘
1670  | _ _ (rel r)  := rel (H _ _ r)
id          └─┘       └─┘  
src         └─┘        └─┘
typ         └─┘       └─┘  
1671  
1672  theorem to_ne : ∀ {l₁ l₂ : list α}, lex (≠) l₁ l₂ → l₁ ≠ l₂
id                             └──┘    └─┘    └┘ └┘   └┘  └┘
src                             └──┘     └─┘               
typ                            └──┘    └─┘    └┘ └┘   └┘  └┘
1673  | _ _ (cons h) e := to_ne h (list.cons.inj e).2
id          └──┘       └───┘    └───────────┘   
src         └──┘                  └───────────┘   
typ         └──┘       └───┘    └───────────┘   
1674  | _ _ (rel r)  e := r (list.cons.inj e).1
id          └─┘           └───────────┘   
src         └─┘             └───────────┘   
typ         └─┘           └───────────┘   
1675  
1676  theorem ne_iff {l₁ l₂ : list α} (H : length l₁ ≤ length l₂) :
id                           └──┘        └────┘ └┘  └────┘ └┘
src                          └──┘         └────┘     └────┘
typ                          └──┘        └────┘ └┘  └────┘ └┘
1677    lex (≠) l₁ l₂ ↔ l₁ ≠ l₂ :=
id     └─┘    └┘ └┘  └┘  └┘
src    └─┘              
typ    └─┘    └┘ └┘  └┘  └┘
1678  ⟨to_ne, λ h, begin
id    └───┘    
src   └───┘
typ   └───┘    
st                └─────
1679    induction l₁ with a l₁ IH generalizing l₂; cases l₂ with b l₂,
id               └┘                                     └┘
src    └────────┘  └───────────────────────────┘  └────┘  └────────┘
typ    └────────┘└┘└───────────────────────────┘  └────┘└┘└────────┘
doc    └────────┘  └───────────────────────────┘  └────┘  └────────┘
txt    └────────┘  └───────────────────────────┘  └────┘  └────────┘
par    └────────┘  └───────────────────────────┘  └────┘  └────────┘
pid               └──────────┘└──────────────┘         └────────┘
st   ──────────────────────────────────────────────────────────────┘└─
1680    { contradiction },
src      └────────────┘
typ      └────────────┘
doc      └────────────┘
txt      └────────────┘
par      └────────────┘
pid                   
st   ───┘└────────────┘└┘
1681    { apply nil },
id             └─┘
src      └────┘└─┘
typ      └────┘└─┘
doc      └────┘   
txt      └────┘   
par      └────┘   
pid              
st   ───┘└────────┘└┘
1682    { exact (not_lt_of_ge H).elim (succ_pos _) },
id              └──────────┘         └──────┘
src      └────┘ └──────────┘ └─────┘ └──────┘└──┘
typ      └────┘ └──────────┘└─────┘ └──────┘└──┘
doc      └────┘              └─────┘         └──┘
txt      └────┘              └─────┘         └──┘
par      └────┘              └─────┘         └──┘
pid                         └─────┘         └─┘
st   ───┘└───────────────────────────────────────┘└┘
1683    { cases classical.em (a = b) with ab ab,
id             └──────────┘    
src      └────┘└──────────┘   └──────────┘
typ      └────┘└──────────┘ └──────────┘
doc      └────┘                └──────────┘
txt      └────┘                └──────────┘
par      └────┘                └──────────┘
pid                           └─────────┘
st   ────────────────────────────────────────┘└─
1684      { subst b, apply cons,
id                       └──┘
src        └────┘   └────┘└──┘
typ        └────┘  └────┘└──┘
doc        └────┘   └────┘
txt        └────┘   └────┘
par        └────┘   └────┘
pid                     
st   ─────┘└─────┘└──────────┘└─
1685        exact IH (le_of_succ_le_succ H) (mt (congr_arg _) h) },
id               └┘  └────────────────┘    └┘  └───────┘    
src        └────┘   └────────────────┘ └┘ └┘ └───────┘└──┘ └┘
typ        └────┘└┘ └────────────────┘└┘ └┘ └───────┘└──┘└┘
doc        └────┘                      └┘             └──┘ └┘
txt        └────┘                      └┘             └──┘ └┘
par        └────┘                      └┘             └──┘ └┘
pid                                   └┘             └──┘ 
st   ──────────────────────────────────────────────────────────┘└┘
1686      { exact rel ab } }
id               └─┘ └┘
src        └────┘└─┘  
typ        └────┘└─┘└┘
doc        └────┘     
txt        └────┘     
par        └────┘     
pid                  
st   ──────────────────┘└───
1687  end⟩
st   ──┘
1688  
1689  end lex
1690  
1691  --Note: this overrides an instance in core lean
1692  instance has_lt' [has_lt α] : has_lt (list α) := ⟨lex (<)⟩
id                     └────┘     └────┘  └──┘       └─┘ 
src                    └────┘      └────┘  └──┘        └─┘ 
typ                    └────┘     └────┘  └──┘       └─┘ 
1693  
1694  theorem nil_lt_cons [has_lt α] (a : α) (l : list α) : [] < a :: l :=
id                        └────┘               └──┘     └┘   └┘ 
src                       └────┘                 └──┘      └┘    └┘
typ                       └────┘               └──┘     └┘   └┘ 
1695  lex.nil
id   └─────┘
src  └─────┘
typ  └─────┘
1696  
1697  instance [linear_order α] : linear_order (list α) :=
id             └──────────┘     └──────────┘  └──┘ 
src            └──────────┘      └──────────┘  └──┘
typ            └──────────┘     └──────────┘  └──┘ 
1698  linear_order_of_STO' (lex (<))
id   └──────────────────┘  └─┘ 
src  └──────────────────┘  └─┘ 
typ  └──────────────────┘  └─┘ 
doc  └──────────────────┘
1699  
1700  --Note: this overrides an instance in core lean
1701  instance has_le' [linear_order α] : has_le (list α) :=
id                     └──────────┘     └────┘  └──┘ 
src                    └──────────┘      └────┘  └──┘
typ                    └──────────┘     └────┘  └──┘ 
1702  preorder.to_has_le _
id   └────────────────┘
src  └────────────────┘
typ  └────────────────┘
1703  
1704  instance [decidable_linear_order α] : decidable_linear_order (list α) :=
id             └────────────────────┘     └────────────────────┘  └──┘ 
src            └────────────────────┘      └────────────────────┘  └──┘
typ            └────────────────────┘     └────────────────────┘  └──┘ 
1705  decidable_linear_order_of_STO' (lex (<))
id   └────────────────────────────┘  └─┘ 
src  └────────────────────────────┘  └─┘ 
typ  └────────────────────────────┘  └─┘ 
doc  └────────────────────────────┘
1706  
1707  /- all & any -/
1708  
1709  @[simp] theorem all_nil (p : α → bool) : all [] p = tt := rfl
id                                   └──┘    └─┘ └┘   └┘    └─┘
src                                   └──┘    └─┘ └┘    └┘    └─┘
typ                                  └──┘    └─┘ └┘   └┘    └─┘
doc    └──┘
1710  
1711  @[simp] theorem all_cons (p : α → bool) (a : α) (l : list α) : all (a::l) p = (p a && all l p) := rfl
id                                    └──┘              └──┘     └─┘  └┘       └┘ └─┘       └─┘
src                                    └──┘               └──┘      └─┘   └┘           └┘ └─┘         └─┘
typ                                   └──┘              └──┘     └─┘  └┘       └┘ └─┘       └─┘
doc    └──┘
1712  
1713  theorem all_iff_forall {p : α → bool} {l : list α} : all l p ↔ ∀ a ∈ l, p a :=
id                                  └──┘       └──┘     └─┘            
src                                  └──┘       └──┘      └─┘     
typ                                 └──┘       └──┘     └─┘            
1714  begin
st   └─────
1715    induction l with a l ih,
id               
src    └────────┘ └──────────┘
typ    └────────┘└──────────┘
doc    └────────┘ └──────────┘
txt    └────────┘ └──────────┘
par    └────────┘ └──────────┘
pid              └─────────┘
st   ────────────────────────┘└─
1716    { exact iff_of_true rfl (forall_mem_nil _) },
id             └─────────┘ └─┘  └────────────┘
src      └────┘└─────────┘└─┘ └────────────┘└──┘
typ      └────┘└─────────┘└─┘ └────────────┘└──┘
doc      └────┘                             └──┘
txt      └────┘                             └──┘
par      └────┘                             └──┘
pid                                        └─┘
st   ───┘└───────────────────────────────────────┘└┘
1717    simp only [all_cons, band_coe_iff, ih, forall_mem_cons]
id                └──────┘  └──────────┘  └┘  └─────────────┘
src    └─────────┘└──────┘└┘└──────────┘└┘  └┘└─────────────┘└┘
typ    └─────────┘└──────┘└┘└──────────┘└┘└┘└┘└─────────────┘└┘
doc    └─────────┘        └┘            └┘  └┘               └┘
txt    └─────────┘        └┘            └┘  └┘               └┘
par    └─────────┘        └┘            └┘  └┘               └┘
pid        └──┘└┘        └┘            └┘  └┘               
st   ─────────────────────────────────────────────────────────┘
1718  end
st   └─┘
1719  
1720  theorem all_iff_forall_prop {p : α → Prop} [decidable_pred p]
id                                              └────────────┘ 
src                                              └────────────┘
typ                                             └────────────┘ 
1721    {l : list α} : all l (λ a, p a) ↔ ∀ a ∈ l, p a :=
id          └──┘     └─┘                   
src         └──┘      └─┘              
typ         └──┘     └─┘                   
1722  by simp only [all_iff_forall, bool.of_to_bool_iff]
id                 └────────────┘  └─────────────────┘
src     └─────────┘└────────────┘└┘└─────────────────┘└─
typ     └─────────┘└────────────┘└┘└─────────────────┘└─
doc     └─────────┘              └┘                   └─
txt     └─────────┘              └┘                   └─
par     └─────────┘              └┘                   └─
pid         └──┘└┘              └┘                   
st     └────────────────────────────────────────────────
1723  
src  
typ  
doc  
txt  
par  
pid  
st   
1724  @[simp] theorem any_nil (p : α → bool) : any [] p = ff := rfl
id                                   └──┘    └─┘ └┘   └┘    └─┘
src                                   └──┘    └─┘ └┘    └┘    └─┘
typ                                  └──┘    └─┘ └┘   └┘    └─┘
doc    └──┘
1725  
1726  @[simp] theorem any_cons (p : α → bool) (a : α) (l : list α) : any (a::l) p = (p a || any l p) := rfl
id                                    └──┘              └──┘     └─┘  └┘       └┘ └─┘       └─┘
src                                    └──┘               └──┘      └─┘   └┘           └┘ └─┘         └─┘
typ                                   └──┘              └──┘     └─┘  └┘       └┘ └─┘       └─┘
doc    └──┘
1727  
1728  theorem any_iff_exists {p : α → bool} {l : list α} : any l p ↔ ∃ a ∈ l, p a :=
id                                  └──┘       └──┘     └─┘          
src                                  └──┘       └──┘      └─┘            
typ                                 └──┘       └──┘     └─┘          
1729  begin
st   └─────
1730    induction l with a l ih,
id               
src    └────────┘ └──────────┘
typ    └────────┘└──────────┘
doc    └────────┘ └──────────┘
txt    └────────┘ └──────────┘
par    └────────┘ └──────────┘
pid              └─────────┘
st   ────────────────────────┘└─
1731    { exact iff_of_false bool.not_ff (not_exists_mem_nil _) },
id             └──────────┘ └─────────┘  └────────────────┘
src      └────┘└──────────┘└─────────┘ └────────────────┘└──┘
typ      └────┘└──────────┘└─────────┘ └────────────────┘└──┘
doc      └────┘                                          └──┘
txt      └────┘                                          └──┘
par      └────┘                                          └──┘
pid                                                     └─┘
st   ───┘└────────────────────────────────────────────────────┘└┘
1732    simp only [any_cons, bor_coe_iff, ih, exists_mem_cons_iff]
id                └──────┘  └─────────┘  └┘  └─────────────────┘
src    └─────────┘└──────┘└┘└─────────┘└┘  └┘└─────────────────┘└┘
typ    └─────────┘└──────┘└┘└─────────┘└┘└┘└┘└─────────────────┘└┘
doc    └─────────┘        └┘           └┘  └┘                   └┘
txt    └─────────┘        └┘           └┘  └┘                   └┘
par    └─────────┘        └┘           └┘  └┘                   └┘
pid        └──┘└┘        └┘           └┘  └┘                   
st   ────────────────────────────────────────────────────────────┘
1733  end
st   └─┘
1734  
1735  theorem any_iff_exists_prop {p : α → Prop} [decidable_pred p]
id                                              └────────────┘ 
src                                              └────────────┘
typ                                             └────────────┘ 
1736    {l : list α} : any l (λ a, p a) ↔ ∃ a ∈ l, p a :=
id          └──┘     └─┘                 
src         └──┘      └─┘                     
typ         └──┘     └─┘                 
1737  by simp [any_iff_exists]
id            └────────────┘
src     └────┘└────────────┘└─
typ     └────┘└────────────┘└─
doc     └────┘              └─
txt     └────┘              └─
par     └────┘              └─
pid                       
st     └──────────────────────
1738  
src  
typ  
doc  
txt  
par  
pid  
st   
1739  theorem any_of_mem {p : α → bool} {a : α} {l : list α} (h₁ : a ∈ l) (h₂ : p a) : any l p :=
id                              └──┘              └──┘                        └─┘  
src                              └──┘               └──┘                             └─┘
typ                             └──┘              └──┘                        └─┘  
1740  any_iff_exists.2 ⟨_, h₁, h₂⟩
id   └────────────┘      └┘  └┘
src  └────────────┘
typ  └────────────┘      └┘  └┘
1741  
1742  @[priority 500] instance decidable_forall_mem {p : α → Prop} [decidable_pred p] (l : list α) :
id                                                                └────────────┘        └──┘ 
src                                                                └────────────┘         └──┘
typ                                                               └────────────┘        └──┘ 
1743    decidable (∀ x ∈ l, p x) :=
id     └───────┘          
src    └───────┘
typ    └───────┘          
1744  decidable_of_iff _ all_iff_forall_prop
id   └──────────────┘   └─────────────────┘
src  └──────────────┘   └─────────────────┘
typ  └──────────────┘   └─────────────────┘
1745  
1746  instance decidable_exists_mem {p : α → Prop} [decidable_pred p] (l : list α) :
id                                                └────────────┘        └──┘ 
src                                                └────────────┘         └──┘
typ                                               └────────────┘        └──┘ 
1747    decidable (∃ x ∈ l, p x) :=
id     └───────┘        
src    └───────┘        
typ    └───────┘        
1748  decidable_of_iff _ any_iff_exists_prop
id   └──────────────┘   └─────────────────┘
src  └──────────────┘   └─────────────────┘
typ  └──────────────┘   └─────────────────┘
1749  
1750  /- map for partial functions -/
1751  
1752  /-- Partial map. If `f : Π a, p a → β` is a partial function defined on
1753    `a : α` satisfying `p`, then `pmap f l h` is essentially the same as `map f l`
1754    but is defined only when all members of `l` satisfy `p`, using the proof
1755    to apply `f`. -/
1756  @[simp] def pmap {p : α → Prop} (f : Π a, p a → β) : Π l : list α, (∀ a ∈ l, p a) → list β
id                                                        └──┘                └──┘ 
src                                                             └──┘                     └──┘
typ                                                       └──┘                └──┘ 
doc    └──┘
1757  | []     H := []
id     └┘          └┘
src    └┘          └┘
typ    └┘          └┘
1758  | (a::l) H := f a (forall_mem_cons.1 H).1 :: pmap l (forall_mem_cons.1 H).2
id      └┘          └─────────────┘      └┘ └──┘    └─────────────┘    
src      └┘             └─────────────┘      └┘         └─────────────┘    
typ     └┘          └─────────────┘      └┘ └──┘    └─────────────┘    
1759  
1760  /-- "Attach" the proof that the elements of `l` are in `l` to produce a new list
1761    with the same elements but in the type `{x // x ∈ l}`. -/
1762  def attach (l : list α) : list {x // x ∈ l} := pmap subtype.mk l (λ a, id)
id                   └──┘     └──┘            └──┘ └────────┘       └┘
src                  └──┘      └──┘               └──┘ └────────┘         └┘
typ                  └──┘     └──┘            └──┘ └────────┘       └┘
doc                                                 └──┘
1763  
1764  theorem pmap_eq_map (p : α → Prop) (f : α → β) (l : list α) (H) :
id                                                    └──┘ 
src                                                      └──┘
typ                                                   └──┘ 
1765    @pmap _ _ p (λ a _, f a) l H = map f l :=
id      └──┘                  └─┘  
src     └──┘                         └─┘
typ     └──┘                  └─┘  
doc     └──┘
1766  by induction l; [refl, simp only [*, pmap, map]]; split; refl
id                                      └──┘  └─┘
src     └────────┘   └──┘  └────────────┘└──┘└┘└─┘   └───┘  └────
typ     └────────┘  └──┘  └────────────┘└──┘└┘└─┘   └───┘  └────
doc     └────────┘    └──┘  └────────────┘└──┘└┘      └───┘  └────
txt     └────────┘    └──┘  └────────────┘    └┘      └───┘  └────
par     └────────┘    └──┘  └────────────┘    └┘      └───┘  └────
pid                            └──┘└───┘    └┘                 
st     └───────────────────────────────────────────────────────────
1767  
src  
typ  
doc  
txt  
par  
pid  
st   
1768  theorem pmap_congr {p q : α → Prop} {f : Π a, p a → β} {g : Π a, q a → β}
id                                                                  
typ                                                                 
1769    (l : list α) {H₁ H₂} (h : ∀ a h₁ h₂, f a h₁ = g a h₂) :
id          └──┘                   └┘ └┘    └┘    └┘
src         └──┘                                   
typ         └──┘                   └┘ └┘    └┘    └┘
1770    pmap f l H₁ = pmap g l H₂ :=
id     └──┘   └┘  └──┘   └┘
src    └──┘         └──┘
typ    └──┘   └┘  └──┘   └┘
doc    └──┘          └──┘
1771  by induction l with _ _ ih; [refl, rw [pmap, pmap, h, ih]]
id                                        └──┘  └──┘  
src     └────────┘ └──────────┘  └──┘  └──┘└──┘└┘└──┘└┘ └┘  
typ     └────────┘└──────────┘  └──┘  └──┘└──┘└┘└──┘└┘└┘└┘
doc     └────────┘ └──────────┘   └──┘  └──┘└──┘└┘└──┘└┘ └┘  
txt     └────────┘ └──────────┘   └──┘  └──┘    └┘    └┘ └┘  
par     └────────┘ └──────────┘   └──┘  └──┘    └┘    └┘ └┘  
pid               └─────────┘           └┘    └┘    └┘ └┘  
st     └───────────────────────────────────┘└──┘└────┘└─┘└──┘
1772  
1773  theorem map_pmap {p : α → Prop} (g : β → γ) (f : Π a, p a → β)
id                                                         
typ                                                        
1774    (l H) : map g (pmap f l H) = pmap (λ a h, g (f a h)) l H :=
id             └─┘   └──┘      └──┘               
src            └─┘    └──┘         └──┘
typ            └─┘   └──┘      └──┘               
doc                   └──┘          └──┘
1775  by induction l; [refl, simp only [*, pmap, map]]; split; refl
id                                      └──┘  └─┘
src     └────────┘   └──┘  └────────────┘└──┘└┘└─┘   └───┘  └────
typ     └────────┘  └──┘  └────────────┘└──┘└┘└─┘   └───┘  └────
doc     └────────┘    └──┘  └────────────┘└──┘└┘      └───┘  └────
txt     └────────┘    └──┘  └────────────┘    └┘      └───┘  └────
par     └────────┘    └──┘  └────────────┘    └┘      └───┘  └────
pid                            └──┘└───┘    └┘                 
st     └───────────────────────────────────────────────────────────
1776  
src  
typ  
doc  
txt  
par  
pid  
st   
1777  theorem pmap_eq_map_attach {p : α → Prop} (f : Π a, p a → β)
id                                                         
typ                                                        
1778    (l H) : pmap f l H = l.attach.map (λ x, f x.1 (H _ x.2)) :=
id             └──┘     └─────┘└──┘             
src            └──┘         └─────┘└──┘                  
typ            └──┘     └─────┘└──┘             
doc            └──┘          └─────┘
1779  by rw [attach, map_pmap]; exact pmap_congr l (λ a h₁ h₂, rfl)
id          └────┘  └──────┘         └────────┘              └─┘
src     └──┘└────┘└┘└──────┘  └────┘└────────┘   └────────┘└─┘└─
typ     └──┘└────┘└┘└──────┘  └────┘└────────┘  └────────┘└─┘└─
doc     └──┘└────┘└┘          └────┘             └────────┘   └─
txt     └──┘      └┘          └────┘             └────────┘   └─
par     └──┘      └┘          └────┘             └────────┘   └─
pid       └┘      └┘                            └────────┘   
st     └─────────┘└────────┘└─────────────────────────────────────
1780  
src  
typ  
doc  
txt  
par  
pid  
st   
1781  theorem attach_map_val (l : list α) : l.attach.map subtype.val = l :=
id                               └──┘     └─────┘└──┘ └─────────┘  
src                              └──┘       └─────┘└──┘ └─────────┘ 
typ                              └──┘     └─────┘└──┘ └─────────┘  
doc                                         └─────┘
1782  by rw [attach, map_pmap]; exact (pmap_eq_map _ _ _ _).trans (map_id l)
id          └────┘  └──────┘          └─────────┘                 └────┘ 
src     └──┘└────┘└┘└──────┘  └────┘ └─────────┘└──────────────┘ └────┘ └─
typ     └──┘└────┘└┘└──────┘  └────┘ └─────────┘└──────────────┘ └────┘└─
doc     └──┘└────┘└┘          └────┘            └──────────────┘        └─
txt     └──┘      └┘          └────┘            └──────────────┘        └─
par     └──┘      └┘          └────┘            └──────────────┘        └─
pid       └┘      └┘                           └──────────────┘        
st     └─────────┘└────────┘└──────────────────────────────────────────────
1783  
src  
typ  
doc  
txt  
par  
pid  
st   
1784  @[simp] theorem mem_attach (l : list α) : ∀ x, x ∈ l.attach | ⟨a, h⟩ :=
id                                   └──┘           └─────┘
src                                  └──┘               └─────┘
typ                                  └──┘           └─────┘
doc    └──┘                                              └─────┘
1785  by have := mem_map.1 (by rw [attach_map_val]; exact h);
id              └─────┘           └────────────┘         
src     └──────┘└─────┘└─┘   └──┘└────────────┘└┘└────┘ 
typ     └──────┘└─────┘└─┘   └──┘└────────────┘└┘└────┘
doc     └──────┘       └─┘   └──┘              └┘└────┘ 
txt     └──────┘       └─┘   └──┘              └┘└────┘ 
par     └──────┘       └─┘   └──┘              └┘└────┘ 
pid     └───┘└─┘       └─┘   └───┘              └───────┘ 
st     └────────────────────┘└─────────────────┘└───────┘└──
1786     { rcases this with ⟨⟨_, _⟩, m, rfl⟩, exact m }
id               └──┘                              
src       └─────┘    └────────────────────┘  └────┘ 
typ       └─────┘└──┘└────────────────────┘  └────┘
doc       └─────┘    └────────────────────┘  └────┘ 
txt       └─────┘    └────────────────────┘  └────┘ 
par       └─────┘    └────────────────────┘  └────┘ 
pid                 └────────────────────┘        
st   ──┘└─────────────────────────────────┘└────────┘└┘
1787  
1788  @[simp] theorem mem_pmap {p : α → Prop} {f : Π a, p a → β}
id                                                       
typ                                                      
doc    └──┘
1789    {l H b} : b ∈ pmap f l H ↔ ∃ a (h : a ∈ l), f a (H a h) = b :=
id                 └──┘                        
src                 └──┘                                  
typ                └──┘                        
doc                  └──┘
1790  by simp only [pmap_eq_map_attach, mem_map, mem_attach, true_and, subtype.exists]
id                 └────────────────┘  └─────┘  └────────┘  └──────┘  └────────────┘
src     └─────────┘└────────────────┘└┘└─────┘└┘└────────┘└┘└──────┘└┘└────────────┘└─
typ     └─────────┘└────────────────┘└┘└─────┘└┘└────────┘└┘└──────┘└┘└────────────┘└─
doc     └─────────┘                  └┘       └┘          └┘        └┘              └─
txt     └─────────┘                  └┘       └┘          └┘        └┘              └─
par     └─────────┘                  └┘       └┘          └┘        └┘              └─
pid         └──┘└┘                  └┘       └┘          └┘        └┘              
st     └──────────────────────────────────────────────────────────────────────────────
1791  
src  
typ  
doc  
txt  
par  
pid  
st   
1792  @[simp] theorem length_pmap {p : α → Prop} {f : Π a, p a → β}
id                                                          
typ                                                         
doc    └──┘
1793    {l H} : length (pmap f l H) = length l :=
id             └────┘  └──┘      └────┘ 
src            └────┘  └──┘         └────┘
typ            └────┘  └──┘      └────┘ 
doc                    └──┘
1794  by induction l; [refl, simp only [*, pmap, length]]
id                                      └──┘  └────┘
src     └────────┘   └──┘  └────────────┘└──┘└┘└────┘
typ     └────────┘  └──┘  └────────────┘└──┘└┘└────┘
doc     └────────┘    └──┘  └────────────┘└──┘└┘      
txt     └────────┘    └──┘  └────────────┘    └┘      
par     └────────┘    └──┘  └────────────┘    └┘      
pid                            └──┘└───┘    └┘      
st     └───────────────────────────────────────────────┘
1795  
1796  @[simp] lemma length_attach (L : list α) : L.attach.length = L.length := length_pmap
id                                    └──┘     └─────┘└─────┘  └─────┘    └─────────┘
src                                   └──┘       └─────┘└─────┘   └─────┘    └─────────┘
typ                                   └──┘     └─────┘└─────┘  └─────┘    └─────────┘
doc    └──┘                                      └─────┘
1797  
1798  /- find -/
1799  
1800  section find
1801  variables {p : α → Prop} [decidable_pred p] {l : list α} {a : α}
id                             └────────────┘         └──┘
src                            └────────────┘         └──┘
typ                            └────────────┘         └──┘
1802  
1803  @[simp] theorem find_nil (p : α → Prop) [decidable_pred p] : find p [] = none :=
id                                           └────────────┘     └──┘  └┘  └──┘
src                                           └────────────┘      └──┘   └┘  └──┘
typ                                          └────────────┘     └──┘  └┘  └──┘
doc    └──┘                                                       └──┘
1804  rfl
id   └─┘
src  └─┘
typ  └─┘
1805  
1806  @[simp] theorem find_cons_of_pos (l) (h : p a) : find p (a::l) = some a :=
id                                                  └──┘   └┘   └──┘ 
src                                                   └──┘     └┘    └──┘
typ                                                 └──┘   └┘   └──┘ 
doc    └──┘                                           └──┘
1807  if_pos h
id   └────┘ 
src  └────┘
typ  └────┘ 
1808  
1809  @[simp] theorem find_cons_of_neg (l) (h : ¬ p a) : find p (a::l) = find p l :=
id                                                   └──┘   └┘   └──┘  
src                                                    └──┘     └┘    └──┘
typ                                                  └──┘   └┘   └──┘  
doc    └──┘                                             └──┘            └──┘
1810  if_neg h
id   └────┘ 
src  └────┘
typ  └────┘ 
1811  
1812  @[simp] theorem find_eq_none : find p l = none ↔ ∀ x ∈ l, ¬ p x :=
id                                  └──┘    └──┘           
src                                 └──┘      └──┘           
typ                                 └──┘    └──┘           
doc    └──┘                         └──┘
1813  begin
st   └─────
1814    induction l with a l IH,
id               
src    └────────┘ └──────────┘
typ    └────────┘└──────────┘
doc    └────────┘ └──────────┘
txt    └────────┘ └──────────┘
par    └────────┘ └──────────┘
pid              └─────────┘
st   ────────────────────────┘└─
1815    { exact iff_of_true rfl (forall_mem_nil _) },
id             └─────────┘ └─┘  └────────────┘
src      └────┘└─────────┘└─┘ └────────────┘└──┘
typ      └────┘└─────────┘└─┘ └────────────┘└──┘
doc      └────┘                             └──┘
txt      └────┘                             └──┘
par      └────┘                             └──┘
pid                                        └─┘
st   ───┘└───────────────────────────────────────┘└┘
1816    rw forall_mem_cons, by_cases h : p a,
id        └─────────────┘                
src    └─┘└─────────────┘  └───────┘ └─┘ 
typ    └─┘└─────────────┘  └───────┘ └─┘
doc    └─┘                 └───────┘ └─┘ 
txt    └─┘                 └───────┘ └─┘ 
par    └─┘                 └───────┘ └─┘ 
pid                                └─┘ 
st   ───────────────────┘└────────────────┘└─
1817    { simp only [find_cons_of_pos _ h, h, not_true, false_and] },
id                  └──────────────┘       └──────┘  └───────┘
src      └─────────┘└──────────────┘└─┘ └┘ └┘└──────┘└┘└───────┘└┘
typ      └─────────┘└──────────────┘└─┘└┘└┘└──────┘└┘└───────┘└┘
doc      └─────────┘                └─┘ └┘ └┘        └┘         └┘
txt      └─────────┘                └─┘ └┘ └┘        └┘         └┘
par      └─────────┘                └─┘ └┘ └┘        └┘         └┘
pid          └──┘└┘                └─┘ └┘ └┘        └┘         
st   ───┘└───────────────────────────────────────────────────────┘└┘
1818    { rwa [find_cons_of_neg _ h, iff_true_intro h, true_and] }
id            └──────────────┘     └────────────┘   └──────┘
src      └───┘└──────────────┘└─┘ └┘└────────────┘ └┘└──────┘└┘
typ      └───┘└──────────────┘└─┘└┘└────────────┘└┘└──────┘└┘
doc      └───┘                └─┘ └┘               └┘        └┘
txt      └───┘                └─┘ └┘               └┘        └┘
par      └───┘                └─┘ └┘               └┘        └┘
pid         └┘                └─┘ └┘               └┘        
st   ────────────────────────────┘└────────────────┘└────────┘└─
1819  end
st   ──┘
1820  
1821  @[simp] theorem find_some (H : find p l = some a) : p a :=
id                                  └──┘    └──┘      
src                                 └──┘      └──┘
typ                                 └──┘    └──┘      
doc    └──┘                         └──┘
1822  begin
st   └─────
1823    induction l with b l IH, {contradiction},
id               
src    └────────┘ └──────────┘   └───────────┘
typ    └────────┘└──────────┘   └───────────┘
doc    └────────┘ └──────────┘   └───────────┘
txt    └────────┘ └──────────┘   └───────────┘
par    └────────┘ └──────────┘   └───────────┘
pid              └─────────┘
st   ────────────────────────┘└──────────────┘└┘
1824    by_cases h : p b,
id                   
src    └───────┘ └─┘ 
typ    └───────┘ └─┘
doc    └───────┘ └─┘ 
txt    └───────┘ └─┘ 
par    └───────┘ └─┘ 
pid             └─┘ 
st   ─────────────────┘└─
1825    { rw find_cons_of_pos _ h at H, cases H, exact h },
id          └──────────────┘                        
src      └─┘└──────────────┘└─┘ └───┘  └────┘   └────┘ 
typ      └─┘└──────────────┘└─┘└───┘  └────┘  └────┘
doc      └─┘                └─┘ └───┘  └────┘   └────┘ 
txt      └─┘                └─┘ └───┘  └────┘   └────┘ 
par      └─┘                └─┘ └───┘  └────┘   └────┘ 
pid                        └─┘ └───┘                
st   ───┘└──────────────────────────┘└───────┘└────────┘└┘
1826    { rw find_cons_of_neg _ h at H, exact IH H }
id          └──────────────┘                └┘ 
src      └─┘└──────────────┘└─┘ └───┘  └────┘   
typ      └─┘└──────────────┘└─┘└───┘  └────┘└┘
doc      └─┘                └─┘ └───┘  └────┘   
txt      └─┘                └─┘ └───┘  └────┘   
par      └─┘                └─┘ └───┘  └────┘   
pid                        └─┘ └───┘          
st   ───────────────────────────────┘└───────────┘└─
1827  end
st   ──┘
1828  
1829  @[simp] theorem find_mem (H : find p l = some a) : a ∈ l :=
id                                 └──┘    └──┘       
src                                └──┘      └──┘        
typ                                └──┘    └──┘       
doc    └──┘                        └──┘
1830  begin
st   └─────
1831    induction l with b l IH, {contradiction},
id               
src    └────────┘ └──────────┘   └───────────┘
typ    └────────┘└──────────┘   └───────────┘
doc    └────────┘ └──────────┘   └───────────┘
txt    └────────┘ └──────────┘   └───────────┘
par    └────────┘ └──────────┘   └───────────┘
pid              └─────────┘
st   ────────────────────────┘└──────────────┘└┘
1832    by_cases h : p b,
id                   
src    └───────┘ └─┘ 
typ    └───────┘ └─┘
doc    └───────┘ └─┘ 
txt    └───────┘ └─┘ 
par    └───────┘ └─┘ 
pid             └─┘ 
st   ─────────────────┘└─
1833    { rw find_cons_of_pos _ h at H, cases H, apply mem_cons_self },
id          └──────────────┘                        └───────────┘
src      └─┘└──────────────┘└─┘ └───┘  └────┘   └────┘└───────────┘
typ      └─┘└──────────────┘└─┘└───┘  └────┘  └────┘└───────────┘
doc      └─┘                └─┘ └───┘  └────┘   └────┘             
txt      └─┘                └─┘ └───┘  └────┘   └────┘             
par      └─┘                └─┘ └───┘  └────┘   └────┘             
pid                        └─┘ └───┘                            
st   ───┘└──────────────────────────┘└───────┘└────────────────────┘└┘
1834    { rw find_cons_of_neg _ h at H, exact mem_cons_of_mem _ (IH H) }
id          └──────────────┘                └─────────────┘    └┘ 
src      └─┘└──────────────┘└─┘ └───┘  └────┘└─────────────┘└─┘    └┘
typ      └─┘└──────────────┘└─┘└───┘  └────┘└─────────────┘└─┘ └┘└┘
doc      └─┘                └─┘ └───┘  └────┘               └─┘    └┘
txt      └─┘                └─┘ └───┘  └────┘               └─┘    └┘
par      └─┘                └─┘ └───┘  └────┘               └─┘    └┘
pid                        └─┘ └───┘                      └─┘    
st   ───────────────────────────────┘└───────────────────────────────┘└─
1835  end
st   ──┘
1836  
1837  end find
1838  
1839  /- lookmap -/
1840  section lookmap
1841  variables (f : α → option α)
id                      └────┘
src                     └────┘
typ                     └────┘
1842  
1843  @[simp] theorem lookmap_nil : [].lookmap f = [] := rfl
id                                 └┘└─────┘    └┘    └─┘
src                                └┘└─────┘     └┘    └─┘
typ                                └┘└─────┘    └┘    └─┘
doc    └──┘                          └─────┘
1844  
1845  @[simp] theorem lookmap_cons_none {a : α} (l : list α) (h : f a = none) :
id                                                 └──┘           └──┘
src                                                 └──┘              └──┘
typ                                                └──┘           └──┘
doc    └──┘
1846    (a :: l).lookmap f = a :: l.lookmap f :=
id       └┘  └─────┘     └┘ └──────┘ 
src       └┘   └─────┘       └┘  └──────┘
typ      └┘  └─────┘     └┘ └──────┘ 
doc            └─────┘            └──────┘
1847  by simp [lookmap, h]
id            └─────┘  
src     └────┘└─────┘└┘ └─
typ     └────┘└─────┘└┘└─
doc     └────┘└─────┘└┘ └─
txt     └────┘       └┘ └─
par     └────┘       └┘ └─
pid                └┘ 
st     └──────────────────
1848  
src  
typ  
doc  
txt  
par  
pid  
st   
1849  @[simp] theorem lookmap_cons_some {a b : α} (l : list α) (h : f a = some b) :
id                                                   └──┘           └──┘ 
src                                                   └──┘              └──┘
typ                                                  └──┘           └──┘ 
doc    └──┘
1850    (a :: l).lookmap f = b :: l :=
id       └┘  └─────┘     └┘ 
src       └┘   └─────┘       └┘
typ      └┘  └─────┘     └┘ 
doc            └─────┘
1851  by simp [lookmap, h]
id            └─────┘  
src     └────┘└─────┘└┘ └─
typ     └────┘└─────┘└┘└─
doc     └────┘└─────┘└┘ └─
txt     └────┘       └┘ └─
par     └────┘       └┘ └─
pid                └┘ 
st     └──────────────────
1852  
src  
typ  
doc  
txt  
par  
pid  
st   
1853  theorem lookmap_some : ∀ l : list α, l.lookmap some = l
id                               └──┘   └──────┘ └──┘  
src                               └──┘     └──────┘ └──┘ 
typ                              └──┘   └──────┘ └──┘  
doc                                        └──────┘
1854  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
1855  | (a::l) := rfl
id       └┘      └─┘
src      └┘      └─┘
typ      └┘      └─┘
1856  
1857  theorem lookmap_none : ∀ l : list α, l.lookmap (λ _, none) = l
id                               └──┘   └──────┘      └──┘   
src                               └──┘     └──────┘       └──┘  
typ                              └──┘   └──────┘      └──┘   
doc                                        └──────┘
1858  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
1859  | (a::l) := congr_arg (cons a) (lookmap_none l)
id      └┘     └───────┘  └──┘     └──────────┘
src      └┘      └───────┘  └──┘
typ     └┘     └───────┘  └──┘     └──────────┘
1860  
1861  theorem lookmap_congr {f g : α → option α} :
id                                   └────┘ 
src                                   └────┘
typ                                  └────┘ 
1862    ∀ {l : list α}, (∀ a ∈ l, f a = g a) → l.lookmap f = l.lookmap g
id           └──┘                    └──────┘   └──────┘ 
src           └──┘                            └──────┘     └──────┘
typ          └──┘                    └──────┘   └──────┘ 
doc                                            └──────┘      └──────┘
1863  | []     H := rfl
id     └┘          └─┘
src    └┘          └─┘
typ    └┘          └─┘
1864  | (a::l) H := begin
id       └┘
src      └┘
typ      └┘
st                 └─────
1865    cases forall_mem_cons.1 H with H₁ H₂,
id           └─────────────┘   
src    └────┘└─────────────┘└─┘ └─────────┘
typ    └────┘└─────────────┘└─┘└─────────┘
doc    └────┘               └─┘ └─────────┘
txt    └────┘               └─┘ └─────────┘
par    └────┘               └─┘ └─────────┘
pid                        └─┘ └─────────┘
st   ─────────────────────────────────────┘└─
1866    cases h : g a with b,
id                
src    └────┘ └─┘  └─────┘
typ    └────┘ └─┘└─────┘
doc    └────┘ └─┘  └─────┘
txt    └────┘ └─┘  └─────┘
par    └────┘ └─┘  └─────┘
pid          └─┘  └─────┘
st   ─────────────────────┘└─
1867    { simp [h, H₁.trans h, lookmap_congr H₂] },
id               └──────┘   └───────────┘ └┘
src      └────┘ └┘└──────┘ └┘               └┘
typ      └────┘└┘└──────┘└┘└───────────┘└┘└┘
doc      └────┘ └┘         └┘               └┘
txt      └────┘ └┘         └┘               └┘
par      └────┘ └┘         └┘               └┘
pid           └┘         └┘               
st   ───┘└─────────────────────────────────────┘└┘
1868    { simp [lookmap_cons_some _ _ h, lookmap_cons_some _ _ (H₁.trans h)] }
id             └───────────────┘       └───────────────┘      └──────┘ 
src      └────┘└───────────────┘└───┘ └┘└───────────────┘└───┘ └──────┘ └─┘
typ      └────┘└───────────────┘└───┘└┘└───────────────┘└───┘ └──────┘└─┘
doc      └────┘                 └───┘ └┘                 └───┘          └─┘
txt      └────┘                 └───┘ └┘                 └───┘          └─┘
par      └────┘                 └───┘ └┘                 └───┘          └─┘
pid                           └───┘ └┘                 └───┘          └┘
st   ──────────────────────────────────────────────────────────────────────┘└─
1869  end
st   ──┘
1870  
1871  theorem lookmap_of_forall_not {l : list α} (H : ∀ a ∈ l, f a = none) : l.lookmap f = l :=
id                                      └──┘                  └──┘    └──────┘   
src                                     └──┘                       └──┘     └──────┘   
typ                                     └──┘                  └──┘    └──────┘   
doc                                                                          └──────┘
1872  (lookmap_congr H).trans (lookmap_none l)
id    └───────────┘  └───┘   └──────────┘ 
src   └───────────┘   └───┘   └──────────┘
typ   └───────────┘  └───┘   └──────────┘ 
1873  
1874  theorem lookmap_map_eq (g : α → β) (h : ∀ a (b ∈ f a), g a = g b) :
id                                                        
src                                                             
typ                                                       
1875    ∀ l : list α, map g (l.lookmap f) = map g l
id          └──┘   └─┘   └──────┘    └─┘  
src          └──┘    └─┘     └──────┘     └─┘
typ         └──┘   └─┘   └──────┘    └─┘  
doc                          └──────┘
1876  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
1877  | (a::l) := begin
id       └┘
src      └┘
typ      └┘
st               └─────
1878    cases h' : f a with b,
id                 
src    └────┘  └─┘  └─────┘
typ    └────┘  └─┘└─────┘
doc    └────┘  └─┘  └─────┘
txt    └────┘  └─┘  └─────┘
par    └────┘  └─┘  └─────┘
pid           └─┘  └─────┘
st   ──────────────────────┘└─
1879    { simp [h', lookmap_map_eq] },
id             └┘  └────────────┘
src      └────┘  └┘              └┘
typ      └────┘└┘└┘└────────────┘└┘
doc      └────┘  └┘              └┘
txt      └────┘  └┘              └┘
par      └────┘  └┘              └┘
pid            └┘              
st   ───┘└────────────────────────┘└┘
1880    { simp [lookmap_cons_some _ _ h', h _ _ h'] }
id             └───────────────┘     └┘       └┘
src      └────┘└───────────────┘└───┘  └┘ └───┘  └┘
typ      └────┘└───────────────┘└───┘└┘└┘└───┘└┘└┘
doc      └────┘                 └───┘  └┘ └───┘  └┘
txt      └────┘                 └───┘  └┘ └───┘  └┘
par      └────┘                 └───┘  └┘ └───┘  └┘
pid                           └───┘  └┘ └───┘  
st   ─────────────────────────────────────────────┘└─
1881  end
st   ──┘
1882  
1883  theorem lookmap_id' (h : ∀ a (b ∈ f a), a = b) (l : list α) : l.lookmap f = l :=
id                                                └──┘     └──────┘   
src                                                     └──┘       └──────┘   
typ                                               └──┘     └──────┘   
doc                                                                 └──────┘
1884  by rw [← map_id (l.lookmap f), lookmap_map_eq, map_id]; exact h
id            └────┘  └───────┘    └────────────┘  └────┘         
src     └────┘└────┘ └───────┘ └─┘└────────────┘└┘└────┘  └────┘ 
typ     └────┘└────┘ └───────┘└─┘└────────────┘└┘└────┘  └────┘
doc     └────┘       └───────┘ └─┘              └┘        └────┘ 
txt     └────┘                 └─┘              └┘        └────┘ 
par     └────┘                 └─┘              └┘        └────┘ 
pid       └──┘                 └─┘              └┘              
st     └─────────────────────────┘└──────────────┘└──────┘└─────────
1885  
src  
typ  
doc  
txt  
par  
pid  
st   
1886  theorem length_lookmap (l : list α) : length (l.lookmap f) = length l :=
id                               └──┘     └────┘  └──────┘    └────┘ 
src                              └──┘      └────┘   └──────┘     └────┘
typ                              └──┘     └────┘  └──────┘    └────┘ 
doc                                                 └──────┘
1887  by rw [← length_map, lookmap_map_eq _ (λ _, ()), length_map]; simp
id            └────────┘  └────────────┘         └┘   └────────┘
src     └────┘└────────┘└┘└────────────┘└─┘  └──┘└┘└─┘└────────┘  └────
typ     └────┘└────────┘└┘└────────────┘└─┘  └──┘└┘└─┘└────────┘  └────
doc     └────┘          └┘              └─┘  └──┘  └─┘            └────
txt     └────┘          └┘              └─┘  └──┘  └─┘            └────
par     └────┘          └┘              └─┘  └──┘  └─┘            └────
pid       └──┘          └┘              └─┘  └──┘  └─┘                
st     └───────────────┘└──────────────────────────┘└──────────┘└──────
1888  
src  
typ  
doc  
txt  
par  
pid  
st   
1889  end lookmap
1890  
1891  /- filter_map -/
1892  
1893  @[simp] theorem filter_map_nil (f : α → option β) : filter_map f [] = [] := rfl
id                                          └────┘     └────────┘  └┘  └┘    └─┘
src                                          └────┘      └────────┘   └┘  └┘    └─┘
typ                                         └────┘     └────────┘  └┘  └┘    └─┘
doc    └──┘
1894  
1895  @[simp] theorem filter_map_cons_none {f : α → option β} (a : α) (l : list α) (h : f a = none) :
id                                                └────┘               └──┘           └──┘
src                                                └────┘                 └──┘              └──┘
typ                                               └────┘               └──┘           └──┘
doc    └──┘
1896    filter_map f (a :: l) = filter_map f l :=
id     └────────┘    └┘    └────────┘  
src    └────────┘      └┘     └────────┘
typ    └────────┘    └┘    └────────┘  
1897  by simp only [filter_map, h]
id                 └────────┘  
src     └─────────┘└────────┘└┘ └─
typ     └─────────┘└────────┘└┘└─
doc     └─────────┘          └┘ └─
txt     └─────────┘          └┘ └─
par     └─────────┘          └┘ └─
pid         └──┘└┘          └┘ 
st     └──────────────────────────
1898  
src  
typ  
doc  
txt  
par  
pid  
st   
1899  @[simp] theorem filter_map_cons_some (f : α → option β)
id                                                └────┘ 
src                                                └────┘
typ                                               └────┘ 
doc    └──┘
1900    (a : α) (l : list α) {b : β} (h : f a = some b) :
id                 └──┘                  └──┘ 
src                 └──┘                      └──┘
typ                └──┘                  └──┘ 
1901    filter_map f (a :: l) = b :: filter_map f l :=
id     └────────┘    └┘     └┘ └────────┘  
src    └────────┘      └┘       └┘ └────────┘
typ    └────────┘    └┘     └┘ └────────┘  
1902  by simp only [filter_map, h]; split; refl
id                 └────────┘  
src     └─────────┘└────────┘└┘   └───┘  └────
typ     └─────────┘└────────┘└┘  └───┘  └────
doc     └─────────┘          └┘   └───┘  └────
txt     └─────────┘          └┘   └───┘  └────
par     └─────────┘          └┘   └───┘  └────
pid         └──┘└┘          └┘              
st     └───────────────────────────────────────
1903  
src  
typ  
doc  
txt  
par  
pid  
st   
1904  theorem filter_map_eq_map (f : α → β) : filter_map (some ∘ f) = map f :=
id                                         └────────┘  └──┘     └─┘ 
src                                          └────────┘  └──┘      └─┘
typ                                        └────────┘  └──┘     └─┘ 
1905  begin
st   └─────
1906    funext l,
src    └──────┘
typ    └──────┘
doc    └──────┘
txt    └──────┘
par    └──────┘
pid          └┘
st   ─────────┘└─
1907    induction l with a l IH, {refl},
id               
src    └────────┘ └──────────┘   └──┘
typ    └────────┘└──────────┘   └──┘
doc    └────────┘ └──────────┘   └──┘
txt    └────────┘ └──────────┘   └──┘
par    └────────┘ └──────────┘   └──┘
pid              └─────────┘
st   ────────────────────────┘└─────┘└┘
1908    simp only [filter_map_cons_some (some ∘ f) _ _ rfl, IH, map_cons], split; refl
id                └──────────────────┘  └──┘        └─┘  └┘  └──────┘
src    └─────────┘└──────────────────┘ └──┘ └────┘└─┘└┘  └┘└──────┘  └───┘  └───┘
typ    └─────────┘└──────────────────┘ └──┘└────┘└─┘└┘└┘└┘└──────┘  └───┘  └───┘
doc    └─────────┘                           └────┘   └┘  └┘          └───┘  └───┘
txt    └─────────┘                           └────┘   └┘  └┘          └───┘  └───┘
par    └─────────┘                           └────┘   └┘  └┘          └───┘  └───┘
pid        └──┘└┘                           └────┘   └┘  └┘                     
st   ──────────────────────────────────────────────────────────────────┘└────────────┘
1909  end
st   └─┘
1910  
1911  theorem filter_map_eq_filter (p : α → Prop) [decidable_pred p] :
id                                               └────────────┘ 
src                                               └────────────┘
typ                                              └────────────┘ 
1912    filter_map (option.guard p) = filter p :=
id     └────────┘  └──────────┘    └────┘ 
src    └────────┘  └──────────┘     └────┘
typ    └────────┘  └──────────┘    └────┘ 
doc                └──────────┘
1913  begin
st   └─────
1914    funext l,
src    └──────┘
typ    └──────┘
doc    └──────┘
txt    └──────┘
par    └──────┘
pid          └┘
st   ─────────┘└─
1915    induction l with a l IH, {refl},
id               
src    └────────┘ └──────────┘   └──┘
typ    └────────┘└──────────┘   └──┘
doc    └────────┘ └──────────┘   └──┘
txt    └────────┘ └──────────┘   └──┘
par    └────────┘ └──────────┘   └──┘
pid              └─────────┘
st   ────────────────────────┘└─────┘└┘
1916    by_cases pa : p a,
id                    
src    └───────┘  └─┘ 
typ    └───────┘  └─┘
doc    └───────┘  └─┘ 
txt    └───────┘  └─┘ 
par    └───────┘  └─┘ 
pid              └─┘ 
st   ──────────────────┘└─
1917    { simp only [filter_map, option.guard, IH, if_pos pa, filter_cons_of_pos _ pa], split; refl },
id                  └────────┘  └──────────┘  └┘  └────┘ └┘  └────────────────┘   └┘
src      └─────────┘└────────┘└┘└──────────┘└┘  └┘└────┘  └┘└────────────────┘└─┘    └───┘  └───┘
typ      └─────────┘└────────┘└┘└──────────┘└┘└┘└┘└────┘└┘└┘└────────────────┘└─┘└┘  └───┘  └───┘
doc      └─────────┘          └┘└──────────┘└┘  └┘        └┘                  └─┘    └───┘  └───┘
txt      └─────────┘          └┘            └┘  └┘        └┘                  └─┘    └───┘  └───┘
par      └─────────┘          └┘            └┘  └┘        └┘                  └─┘    └───┘  └───┘
pid          └──┘└┘          └┘            └┘  └┘        └┘                  └─┘               
st   ───┘└──────────────────────────────────────────────────────────────────────────┘└────────────┘└┘
1918    { simp only [filter_map, option.guard, IH, if_neg pa, filter_cons_of_neg _ pa] }
id                  └────────┘  └──────────┘  └┘  └────┘ └┘  └────────────────┘   └┘
src      └─────────┘└────────┘└┘└──────────┘└┘  └┘└────┘  └┘└────────────────┘└─┘  └┘
typ      └─────────┘└────────┘└┘└──────────┘└┘└┘└┘└────┘└┘└┘└────────────────┘└─┘└┘└┘
doc      └─────────┘          └┘└──────────┘└┘  └┘        └┘                  └─┘  └┘
txt      └─────────┘          └┘            └┘  └┘        └┘                  └─┘  └┘
par      └─────────┘          └┘            └┘  └┘        └┘                  └─┘  └┘
pid          └──┘└┘          └┘            └┘  └┘        └┘                  └─┘  
st   ────────────────────────────────────────────────────────────────────────────────┘└─
1919  end
st   ──┘
1920  
1921  theorem filter_map_filter_map (f : α → option β) (g : β → option γ) (l : list α) :
id                                         └────┘           └────┘        └──┘ 
src                                         └────┘             └────┘         └──┘
typ                                        └────┘           └────┘        └──┘ 
1922    filter_map g (filter_map f l) = filter_map (λ x, (f x).bind g) l :=
id     └────────┘   └────────┘     └────────┘         └──┘    
src    └────────┘    └────────┘       └────────┘            └──┘
typ    └────────┘   └────────┘     └────────┘         └──┘    
1923  begin
st   └─────
1924    induction l with a l IH, {refl},
id               
src    └────────┘ └──────────┘   └──┘
typ    └────────┘└──────────┘   └──┘
doc    └────────┘ └──────────┘   └──┘
txt    └────────┘ └──────────┘   └──┘
par    └────────┘ └──────────┘   └──┘
pid              └─────────┘
st   ────────────────────────┘└─────┘└┘
1925    cases h : f a with b,
id                
src    └────┘ └─┘  └─────┘
typ    └────┘ └─┘└─────┘
doc    └────┘ └─┘  └─────┘
txt    └────┘ └─┘  └─────┘
par    └────┘ └─┘  └─────┘
pid          └─┘  └─────┘
st   ─────────────────────┘└─
1926    { rw [filter_map_cons_none _ _ h, filter_map_cons_none, IH],
id           └──────────────────┘       └──────────────────┘  └┘
src      └──┘└──────────────────┘└───┘ └┘└──────────────────┘└┘  
typ      └──┘└──────────────────┘└───┘└┘└──────────────────┘└┘└┘
doc      └──┘                    └───┘ └┘                    └┘  
txt      └──┘                    └───┘ └┘                    └┘  
par      └──┘                    └───┘ └┘                    └┘  
pid        └┘                    └───┘ └┘                    └┘  
st   ───┘└────────────────────────────┘└────────────────────┘└──┘└─
1927      simp only [h, option.none_bind'] },
id                    └───────────────┘
src      └─────────┘ └┘└───────────────┘└┘
typ      └─────────┘└┘└───────────────┘└┘
doc      └─────────┘ └┘                 └┘
txt      └─────────┘ └┘                 └┘
par      └─────────┘ └┘                 └┘
pid          └──┘└┘ └┘                 
st   ────────────────────────────────────┘└┘
1928    rw filter_map_cons_some _ _ _ h,
id        └──────────────────┘       
src    └─┘└──────────────────┘└─────┘
typ    └─┘└──────────────────┘└─────┘
doc    └─┘                    └─────┘
txt    └─┘                    └─────┘
par    └─┘                    └─────┘
pid                          └─────┘
st   ────────────────────────────────┘└─
1929    cases h' : g b with c;
id                 
src    └────┘  └─┘  └─────┘
typ    └────┘  └─┘└─────┘
doc    └────┘  └─┘  └─────┘
txt    └────┘  └─┘  └─────┘
par    └────┘  └─┘  └─────┘
pid           └─┘  └─────┘
st   ─────────────────────────
1930    [ rw [filter_map_cons_none _ _ h', filter_map_cons_none, IH],
id          └──────────────────┘     └┘  └──────────────────┘  └┘
src     └──┘└──────────────────┘└───┘  └┘└──────────────────┘└┘  
typ     └──┘└──────────────────┘└───┘└┘└┘└──────────────────┘└┘└┘
doc      └──┘                    └───┘  └┘                    └┘  
txt      └──┘                    └───┘  └┘                    └┘  
par      └──┘                    └───┘  └┘                    └┘  
pid        └┘                    └───┘  └┘                    └┘  
st   ───────┘└─────────────────────────┘└────────────────────┘└──┘└─
1931      rw [filter_map_cons_some _ _ _ h', filter_map_cons_some, IH] ];
id           └──────────────────┘       └┘  └──────────────────┘  └┘
src      └──┘└──────────────────┘└─────┘  └┘└──────────────────┘└┘  └┘
typ      └──┘└──────────────────┘└─────┘└┘└┘└──────────────────┘└┘└┘└┘
doc      └──┘                    └─────┘  └┘                    └┘  └┘
txt      └──┘                    └─────┘  └┘                    └┘  └┘
par      └──┘                    └─────┘  └┘                    └┘  └┘
pid        └┘                    └─────┘  └┘                    └┘  
st   ───────┘└───────────────────────────┘└────────────────────┘└──┘└───
1932    simp only [h, h', option.some_bind']
id                  └┘  └───────────────┘
src    └─────────┘ └┘  └┘└───────────────┘└┘
typ    └─────────┘└┘└┘└┘└───────────────┘└┘
doc    └─────────┘ └┘  └┘                 └┘
txt    └─────────┘ └┘  └┘                 └┘
par    └─────────┘ └┘  └┘                 └┘
pid        └──┘└┘ └┘  └┘                 
st   ──────────────────────────────────────┘
1933  end
st   └─┘
1934  
1935  theorem map_filter_map (f : α → option β) (g : β → γ) (l : list α) :
id                                  └────┘                  └──┘ 
src                                  └────┘                     └──┘
typ                                 └────┘                  └──┘ 
1936    map g (filter_map f l) = filter_map (λ x, (f x).map g) l :=
id     └─┘   └────────┘     └────────┘         └─┘    
src    └─┘    └────────┘       └────────┘            └─┘
typ    └─┘   └────────┘     └────────┘         └─┘    
1937  by rw [← filter_map_eq_map, filter_map_filter_map]; refl
id            └───────────────┘  └───────────────────┘
src     └────┘└───────────────┘└┘└───────────────────┘  └────
typ     └────┘└───────────────┘└┘└───────────────────┘  └────
doc     └────┘                 └┘                       └────
txt     └────┘                 └┘                       └────
par     └────┘                 └┘                       └────
pid       └──┘                 └┘                           
st     └──────────────────────┘└─────────────────────┘└──────
1938  
src  
typ  
doc  
txt  
par  
pid  
st   
1939  theorem filter_map_map (f : α → β) (g : β → option γ) (l : list α) :
id                                            └────┘        └──┘ 
src                                              └────┘         └──┘
typ                                           └────┘        └──┘ 
1940    filter_map g (map f l) = filter_map (g ∘ f) l :=
id     └────────┘   └─┘     └────────┘      
src    └────────┘    └─┘       └────────┘    
typ    └────────┘   └─┘     └────────┘      
1941  by rw [← filter_map_eq_map, filter_map_filter_map]; refl
id            └───────────────┘  └───────────────────┘
src     └────┘└───────────────┘└┘└───────────────────┘  └────
typ     └────┘└───────────────┘└┘└───────────────────┘  └────
doc     └────┘                 └┘                       └────
txt     └────┘                 └┘                       └────
par     └────┘                 └┘                       └────
pid       └──┘                 └┘                           
st     └──────────────────────┘└─────────────────────┘└──────
1942  
src  
typ  
doc  
txt  
par  
pid  
st   
1943  theorem filter_filter_map (f : α → option β) (p : β → Prop) [decidable_pred p] (l : list α) :
id                                     └────┘                  └────────────┘        └──┘ 
src                                     └────┘                    └────────────┘         └──┘
typ                                    └────┘                  └────────────┘        └──┘ 
1944    filter p (filter_map f l) = filter_map (λ x, (f x).filter p) l :=
id     └────┘   └────────┘     └────────┘         └────┘    
src    └────┘    └────────┘       └────────┘            └────┘
typ    └────┘   └────────┘     └────────┘         └────┘    
doc                                                      └────┘
1945  by rw [← filter_map_eq_filter, filter_map_filter_map]; refl
id            └──────────────────┘  └───────────────────┘
src     └────┘└──────────────────┘└┘└───────────────────┘  └────
typ     └────┘└──────────────────┘└┘└───────────────────┘  └────
doc     └────┘                    └┘                       └────
txt     └────┘                    └┘                       └────
par     └────┘                    └┘                       └────
pid       └──┘                    └┘                           
st     └─────────────────────────┘└─────────────────────┘└──────
1946  
src  
typ  
doc  
txt  
par  
pid  
st   
1947  theorem filter_map_filter (p : α → Prop) [decidable_pred p] (f : α → option β) (l : list α) :
id                                            └────────────┘           └────┘        └──┘ 
src                                            └────────────┘             └────┘         └──┘
typ                                           └────────────┘           └────┘        └──┘ 
1948    filter_map f (filter p l) = filter_map (λ x, if p x then f x else none) l :=
id     └────────┘   └────┘     └────────┘                       └──┘  
src    └────────┘    └────┘       └────────┘                            └──┘
typ    └────────┘   └────┘     └────────┘                       └──┘  
1949  begin
st   └─────
1950    rw [← filter_map_eq_filter, filter_map_filter_map], congr,
id           └──────────────────┘  └───────────────────┘
src    └────┘└──────────────────┘└┘└───────────────────┘  └───┘
typ    └────┘└──────────────────┘└┘└───────────────────┘  └───┘
doc    └────┘                    └┘                     
txt    └────┘                    └┘                       └───┘
par    └────┘                    └┘                       └───┘
pid      └──┘                    └┘                     
st   ───────────────────────────┘└─────────────────────┘└──────┘└─
1951    funext x,
src    └──────┘
typ    └──────┘
doc    └──────┘
txt    └──────┘
par    └──────┘
pid          └┘
st   ─────────┘└─
1952    show (option.guard p x).bind f = ite (p x) (f x) none,
id           └──────────┘              └─┘          └──┘
src    └───┘ └──────────┘  └─────┘ └─┘   └┘   └┘└──┘
typ    └───┘ └──────────┘  └─────┘ └─┘  └┘ └┘└──┘
doc    └───┘ └──────────┘  └─────┘        └┘   └┘
txt    └───┘               └─────┘        └┘   └┘
par    └───┘               └─────┘        └┘   └┘
pid    └───┘               └─────┘        └┘   └┘
st   ─────────────────────────────────────────────────────────
1953    by_cases h : p x,
id                   
src    └───────┘ └─┘ 
typ    └───────┘ └─┘
doc    └───────┘ └─┘ 
txt    └───────┘ └─┘ 
par    └───────┘ └─┘ 
pid             └─┘ 
st   ─────────────────┘└─
1954    { simp only [option.guard, if_pos h, option.some_bind'] },
id                  └──────────┘  └────┘   └───────────────┘
src      └─────────┘└──────────┘└┘└────┘ └┘└───────────────┘└┘
typ      └─────────┘└──────────┘└┘└────┘└┘└───────────────┘└┘
doc      └─────────┘└──────────┘└┘       └┘                 └┘
txt      └─────────┘            └┘       └┘                 └┘
par      └─────────┘            └┘       └┘                 └┘
pid          └──┘└┘            └┘       └┘                 
st   ───┘└────────────────────────────────────────────────────┘└┘
1955    { simp only [option.guard, if_neg h, option.none_bind'] }
id                  └──────────┘  └────┘   └───────────────┘
src      └─────────┘└──────────┘└┘└────┘ └┘└───────────────┘└┘
typ      └─────────┘└──────────┘└┘└────┘└┘└───────────────┘└┘
doc      └─────────┘└──────────┘└┘       └┘                 └┘
txt      └─────────┘            └┘       └┘                 └┘
par      └─────────┘            └┘       └┘                 └┘
pid          └──┘└┘            └┘       └┘                 
st   ─────────────────────────────────────────────────────────┘└─
1956  end
st   ──┘
1957  
1958  @[simp] theorem filter_map_some (l : list α) : filter_map some l = l :=
id                                        └──┘     └────────┘ └──┘   
src                                       └──┘      └────────┘ └──┘   
typ                                       └──┘     └────────┘ └──┘   
doc    └──┘
1959  by rw filter_map_eq_map; apply map_id
id         └───────────────┘        └────┘
src     └─┘└───────────────┘  └────┘└────┘
typ     └─┘└───────────────┘  └────┘└────┘
doc     └─┘                   └────┘      
txt     └─┘                   └────┘      
par     └─┘                   └────┘      
pid                                     
st     └───────────────────────────────────
1960  
src  
typ  
doc  
txt  
par  
pid  
st   
1961  @[simp] theorem mem_filter_map (f : α → option β) (l : list α) {b : β} :
id                                          └────┘        └──┘        
src                                          └────┘         └──┘
typ                                         └────┘        └──┘        
doc    └──┘
1962    b ∈ filter_map f l ↔ ∃ a, a ∈ l ∧ f a = some b :=
id       └────────┘             └──┘ 
src       └────────┘                    └──┘
typ      └────────┘             └──┘ 
1963  begin
st   └─────
1964    induction l with a l IH,
id               
src    └────────┘ └──────────┘
typ    └────────┘└──────────┘
doc    └────────┘ └──────────┘
txt    └────────┘ └──────────┘
par    └────────┘ └──────────┘
pid              └─────────┘
st   ────────────────────────┘└─
1965    { split, { intro H, cases H }, { rintro ⟨_, H, _⟩, cases H } },
id                                                             
src      └───┘    └─────┘  └────┘      └──────────────┘  └────┘ 
typ      └───┘    └─────┘  └────┘     └──────────────┘  └────┘
doc      └───┘    └─────┘  └────┘      └──────────────┘  └────┘ 
txt      └───┘    └─────┘  └────┘      └──────────────┘  └────┘ 
par      └───┘    └─────┘  └────┘      └──────────────┘  └────┘ 
pid                    └┘                   └────────┘        
st   ───┘└───┘└──┘└─────┘└────────┘└┘└─────────────────┘└────────┘└──┘
1966    cases h : f a with b',
id                
src    └────┘ └─┘  └──────┘
typ    └────┘ └─┘└──────┘
doc    └────┘ └─┘  └──────┘
txt    └────┘ └─┘  └──────┘
par    └────┘ └─┘  └──────┘
pid          └─┘  └──────┘
st   ──────────────────────┘└─
1967    { have : f a ≠ some b, {rw h, intro, contradiction},
id                 └──┘       
src      └─────┘  └──┘    └─┘   └───┘  └───────────┘
typ      └─────┘└──┘   └─┘  └───┘  └───────────┘
doc      └─────┘           └─┘   └───┘  └───────────┘
txt      └─────┘           └─┘   └───┘  └───────────┘
par      └─────┘           └─┘   └───┘  └───────────┘
pid      └───┘└┘             
st   ───┘└─────────────────┘└────┘└─────┘└─────────────┘└┘
1968      simp only [filter_map_cons_none _ _ h, IH, mem_cons_iff,
id                  └──────────────────┘       └┘  └──────────┘
src      └─────────┘└──────────────────┘└───┘ └┘  └┘└──────────┘└─
typ      └─────────┘└──────────────────┘└───┘└┘└┘└┘└──────────┘└─
doc      └─────────┘                    └───┘ └┘  └┘            └─
txt      └─────────┘                    └───┘ └┘  └┘            └─
par      └─────────┘                    └───┘ └┘  └┘            └─
pid          └──┘└┘                    └───┘ └┘  └┘            └─
st   ─────────────────────────────────────────────────────────────
1969        or_and_distrib_right, exists_or_distrib, exists_eq_left, this, false_or] },
id         └──────────────────┘  └───────────────┘  └────────────┘  └──┘  └──────┘
src  ─────┘└──────────────────┘└┘└───────────────┘└┘└────────────┘└┘    └┘└──────┘└┘
typ  ─────┘└──────────────────┘└┘└───────────────┘└┘└────────────┘└┘└──┘└┘└──────┘└┘
doc  ─────┘                    └┘                 └┘              └┘    └┘        └┘
txt  ─────┘                    └┘                 └┘              └┘    └┘        └┘
par  ─────┘                    └┘                 └┘              └┘    └┘        └┘
pid  ─────┘                    └┘                 └┘              └┘    └┘        
st   ──────────────────────────────────────────────────────────────────────────────┘└┘
1970    { have : f a = some b ↔ b = b',
id                  └──┘        └┘
src      └─────┘   └──┘    
typ      └─────┘ └──┘   └┘
doc      └─────┘           
txt      └─────┘           
par      └─────┘           
pid      └───┘└┘           
st   ───────────────────────────────┘└─
1971      { split; intro t, {rw t at h; injection h}, {exact t.symm ▸ h} },
id                                                        └────┘  
src        └───┘  └─────┘   └─┘ └───┘  └────────┘     └────┘└────┘
typ        └───┘  └─────┘   └─┘└───┘  └────────┘    └────┘└────┘
doc        └───┘  └─────┘   └─┘ └───┘  └────────┘     └────┘       
txt        └───┘  └─────┘   └─┘ └───┘  └────────┘     └────┘       
par        └───┘  └─────┘   └─┘ └───┘  └────────┘     └────┘       
pid                    └┘      └───┘                            
st   ─────┘└────────────┘└────┘└────────────────┘└┘└────────────────┘└──┘
1972        simp only [filter_map_cons_some _ _ _ h, IH, mem_cons_iff,
id                    └──────────────────┘         └┘  └──────────┘
src        └─────────┘└──────────────────┘└─────┘ └┘  └┘└──────────┘└─
typ        └─────────┘└──────────────────┘└─────┘└┘└┘└┘└──────────┘└─
doc        └─────────┘                    └─────┘ └┘  └┘            └─
txt        └─────────┘                    └─────┘ └┘  └┘            └─
par        └─────────┘                    └─────┘ └┘  └┘            └─
pid            └──┘└┘                    └─────┘ └┘  └┘            └─
st   ─────────────────────────────────────────────────────────────────
1973          or_and_distrib_right, exists_or_distrib, this, exists_eq_left] }
id           └──────────────────┘  └───────────────┘  └──┘  └────────────┘
src  ───────┘└──────────────────┘└┘└───────────────┘└┘    └┘└────────────┘└┘
typ  ───────┘└──────────────────┘└┘└───────────────┘└┘└──┘└┘└────────────┘└┘
doc  ───────┘                    └┘                 └┘    └┘              └┘
txt  ───────┘                    └┘                 └┘    └┘              └┘
par  ───────┘                    └┘                 └┘    └┘              └┘
pid  ───────┘                    └┘                 └┘    └┘              
st   ──────────────────────────────────────────────────────────────────────┘└─
1974  end
st   ──┘
1975  
1976  theorem map_filter_map_of_inv (f : α → option β) (g : β → α)
id                                         └────┘           
src                                         └────┘
typ                                        └────┘           
1977    (H : ∀ x : α, (f x).map g = some x) (l : list α) :
id                     └─┘    └──┘        └──┘ 
src                       └─┘     └──┘         └──┘
typ                    └─┘    └──┘        └──┘ 
1978    map g (filter_map f l) = l :=
id     └─┘   └────────┘     
src    └─┘    └────────┘      
typ    └─┘   └────────┘     
1979  by simp only [map_filter_map, H, filter_map_some]
id                 └────────────┘    └─────────────┘
src     └─────────┘└────────────┘└┘ └┘└─────────────┘└─
typ     └─────────┘└────────────┘└┘└┘└─────────────┘└─
doc     └─────────┘              └┘ └┘               └─
txt     └─────────┘              └┘ └┘               └─
par     └─────────┘              └┘ └┘               └─
pid         └──┘└┘              └┘ └┘               
st     └───────────────────────────────────────────────
1980  
src  
typ  
doc  
txt  
par  
pid  
st   
1981  theorem filter_map_sublist_filter_map (f : α → option β) {l₁ l₂ : list α}
id                                                 └────┘            └──┘ 
src                                                 └────┘             └──┘
typ                                                └────┘            └──┘ 
1982    (s : l₁ <+ l₂) : filter_map f l₁ <+ filter_map f l₂ :=
id          └┘ └┘ └┘    └────────┘  └┘ └┘ └────────┘  └┘
src            └┘       └────────┘      └┘ └────────┘
typ         └┘ └┘ └┘    └────────┘  └┘ └┘ └────────┘  └┘
1983  by induction s with l₁ l₂ a s IH l₁ l₂ a s IH;
id                
src     └────────┘ └─────────────────────────────┘
typ     └────────┘└─────────────────────────────┘
doc     └────────┘ └─────────────────────────────┘
txt     └────────┘ └─────────────────────────────┘
par     └────────┘ └─────────────────────────────┘
pid               └────────────────────────────┘
st     └────────────────────────────────────────────
1984     simp only [filter_map]; cases f a with b;
id                 └────────┘          
src     └─────────┘└────────┘  └────┘  └─────┘
typ     └─────────┘└────────┘  └────┘└─────┘
doc     └─────────┘            └────┘  └─────┘
txt     └─────────┘            └────┘  └─────┘
par     └─────────┘            └────┘  └─────┘
pid         └──┘└┘                   └─────┘
st   ─────────────────────────────────────────────
1985     simp only [filter_map, IH, sublist.cons, sublist.cons2]
id                 └────────┘  └┘  └──────────┘  └───────────┘
src     └─────────┘└────────┘└┘  └┘└──────────┘└┘└───────────┘└─
typ     └─────────┘└────────┘└┘└┘└┘└──────────┘└┘└───────────┘└─
doc     └─────────┘          └┘  └┘            └┘             └─
txt     └─────────┘          └┘  └┘            └┘             └─
par     └─────────┘          └┘  └┘            └┘             └─
pid         └──┘└┘          └┘  └┘            └┘             
st   ───────────────────────────────────────────────────────────
1986  
src  
typ  
doc  
txt  
par  
pid  
st   
1987  theorem map_sublist_map (f : α → β) {l₁ l₂ : list α}
id                                              └──┘ 
src                                               └──┘
typ                                             └──┘ 
1988    (s : l₁ <+ l₂) : map f l₁ <+ map f l₂ :=
id          └┘ └┘ └┘    └─┘  └┘ └┘ └─┘  └┘
src            └┘       └─┘      └┘ └─┘
typ         └┘ └┘ └┘    └─┘  └┘ └┘ └─┘  └┘
1989  by rw ← filter_map_eq_map; exact filter_map_sublist_filter_map _ s
id           └───────────────┘        └───────────────────────────┘   
src     └───┘└───────────────┘  └────┘└───────────────────────────┘└─┘ 
typ     └───┘└───────────────┘  └────┘└───────────────────────────┘└─┘
doc     └───┘                   └────┘                             └─┘ 
txt     └───┘                   └────┘                             └─┘ 
par     └───┘                   └────┘                             └─┘ 
pid       └─┘                                                     └─┘ 
st     └────────────────────────────────────────────────────────────────
1990  
src  
typ  
doc  
txt  
par  
pid  
st   
1991  /- filter -/
src  ─────────────
typ  ─────────────
doc  ─────────────
txt  ─────────────
par  ─────────────
pid  ─────────────
st   ─────────────
1992  
src  
typ  
doc  
txt  
par  
pid  
st   
1993  section filter
1994  variables {p : α → Prop} [decidable_pred p]
id                             └────────────┘
src                            └────────────┘
typ                            └────────────┘
1995  
1996  lemma filter_congr {p q : α → Prop} [decidable_pred p] [decidable_pred q]
id                                       └────────────┘    └────────────┘ 
src                                       └────────────┘     └────────────┘
typ                                      └────────────┘    └────────────┘ 
1997    : ∀ {l : list α}, (∀ x ∈ l, p x ↔ q x) → filter p l = filter q l
id             └──┘                    └────┘    └────┘  
src             └──┘                           └────┘      └────┘
typ            └──┘                    └────┘    └────┘  
1998  | [] _     := rfl
id     └┘          └─┘
src    └┘          └─┘
typ    └┘          └─┘
1999  | (a::l) h := by rw forall_mem_cons at h; by_cases pa : p a;
id       └┘              └─────────────┘                      
src      └┘           └─┘└─────────────┘└───┘  └───────┘  └─┘ 
typ      └┘           └─┘└─────────────┘└───┘  └───────┘  └─┘
doc                   └─┘               └───┘  └───────┘  └─┘ 
txt                   └─┘               └───┘  └───────┘  └─┘ 
par                   └─┘               └───┘  └───────┘  └─┘ 
pid                                    └───┘            └─┘ 
st                   └────────────────────────────────────────────
2000    [simp only [filter_cons_of_pos _ pa, filter_cons_of_pos _ (h.1.1 pa), filter_congr h.2],
id                └────────────────┘   └┘  └────────────────┘         └┘   └──────────┘ 
src    └─────────┘└────────────────┘└─┘  └┘└────────────────┘└─┘  └───┘  └─┘             └─┘
typ    └─────────┘└────────────────┘└─┘└┘└┘└────────────────┘└─┘ └───┘└┘└─┘└──────────┘└─┘
doc     └─────────┘                  └─┘  └┘                  └─┘  └───┘  └─┘             └─┘
txt     └─────────┘                  └─┘  └┘                  └─┘  └───┘  └─┘             └─┘
par     └─────────┘                  └─┘  └┘                  └─┘  └───┘  └─┘             └─┘
pid         └──┘└┘                  └─┘  └┘                  └─┘  └───┘  └─┘             └─┘
st   ───────────────────────────────────────────────────────────────────────────────────────────
2001     simp only [filter_cons_of_neg _ pa, filter_cons_of_neg _ (mt h.1.2 pa), filter_congr h.2]]; split; refl
id                 └────────────────┘   └┘  └────────────────┘    └┘      └┘   └──────────┘ 
src     └─────────┘└────────────────┘└─┘  └┘└────────────────┘└─┘ └┘ └───┘  └─┘             └─┘   └───┘  └────
typ     └─────────┘└────────────────┘└─┘└┘└┘└────────────────┘└─┘ └┘└───┘└┘└─┘└──────────┘└─┘   └───┘  └────
doc     └─────────┘                  └─┘  └┘                  └─┘    └───┘  └─┘             └─┘   └───┘  └────
txt     └─────────┘                  └─┘  └┘                  └─┘    └───┘  └─┘             └─┘   └───┘  └────
par     └─────────┘                  └─┘  └┘                  └─┘    └───┘  └─┘             └─┘   └───┘  └────
pid         └──┘└┘                  └─┘  └┘                  └─┘    └───┘  └─┘             └─┘              
st   ───────────────────────────────────────────────────────────────────────────────────────────────────────────
2002  
src  
typ  
doc  
txt  
par  
pid  
st   
2003  @[simp] theorem filter_subset (l : list α) : filter p l ⊆ l :=
id                                      └──┘     └────┘    
src                                     └──┘      └────┘     
typ                                     └──┘     └────┘    
doc    └──┘
2004  subset_of_sublist $ filter_sublist l
id   └───────────────┘   └────────────┘ 
src  └───────────────┘   └────────────┘
typ  └───────────────┘   └────────────┘ 
2005  
2006  theorem of_mem_filter {a : α} : ∀ {l}, a ∈ filter p l → p a
id                                         └────┘      
src                                            └────┘
typ                                        └────┘      
2007  | (b::l) ain :=
id      └┘
src      └┘
typ     └┘
2008    if pb : p b then
id     └┘      
src    └┘
typ    └┘      
2009      have a ∈ b :: filter p l, by simpa only [filter_cons_of_pos _ pb] using ain,
id                └┘ └────┘                    └────────────────┘   └┘        └─┘
src                └┘ └────┘         └──────────┘└────────────────┘└─┘  └──────┘
typ               └┘ └────┘        └──────────┘└────────────────┘└─┘└┘└──────┘└─┘
doc                                   └──────────┘                  └─┘  └──────┘
txt                                   └──────────┘                  └─┘  └──────┘
par                                   └──────────┘                  └─┘  └──────┘
pid                                        └──┘└┘                  └─┘  └────┘
st                                   └─────────────────────────────────────────────┘
2010      or.elim (eq_or_mem_of_mem_cons this)
id       └─────┘  └───────────────────┘ └──┘
src      └─────┘  └───────────────────┘
typ      └─────┘  └───────────────────┘ └──┘
2011        (assume : a = b, begin rw [← this] at pb, exact pb end)
id                                    └──┘               └┘
src                              └────┘    └─────┘  └────┘  
typ                             └────┘└──┘└─────┘  └────┘└┘
doc                               └────┘    └─────┘  └────┘  
txt                               └────┘    └─────┘  └────┘  
par                               └────┘    └─────┘  └────┘  
pid                                 └──┘    └────┘         
st                          └──────────────┘└────┘└─────────┘└─┘
2012        (assume : a ∈ filter p l, of_mem_filter this)
id                     └────┘     └───────────┘ └──┘
src                     └────┘
typ                    └────┘     └───────────┘ └──┘
2013    else
2014      begin simp only [filter_cons_of_neg _ pb] at ain, exact (of_mem_filter ain) end
id                        └────────────────┘   └┘                 └───────────┘ └─┘  └─┘
src            └─────────┘└────────────────┘└─┘  └──────┘  └────┘                 └┘
typ            └─────────┘└────────────────┘└─┘└┘└──────┘  └────┘ └───────────┘└─┘└┘└─┘
doc            └─────────┘                  └─┘  └──────┘  └────┘                 └┘
txt            └─────────┘                  └─┘  └──────┘  └────┘                 └┘
par            └─────────┘                  └─┘  └──────┘  └────┘                 └┘
pid                └──┘└┘                  └─┘  └────┘                        
st       └──────────────────────────────────────────────┘└──────────────────────────┘└─┘
2015  
2016  theorem mem_of_mem_filter {a : α} {l} (h : a ∈ filter p l) : a ∈ l :=
id                                               └────┘        
src                                                └────┘          
typ                                              └────┘        
2017  filter_subset l h
id   └───────────┘  
src  └───────────┘
typ  └───────────┘  
2018  
2019  theorem mem_filter_of_mem {a : α} : ∀ {l}, a ∈ l → p a → a ∈ filter p l
id                                                      └────┘  
src                                                             └────┘
typ                                                     └────┘  
2020  | (_::l) (or.inl rfl) pa := by rw filter_cons_of_pos _ pa; apply mem_cons_self
id       └┘    └────┘ └─┘              └────────────────┘   └┘        └───────────┘
src      └┘    └────┘ └─┘           └─┘└────────────────┘└─┘    └────┘└───────────┘
typ      └┘    └────┘ └─┘           └─┘└────────────────┘└─┘└┘  └────┘└───────────┘
doc                                 └─┘                  └─┘    └────┘             
txt                                 └─┘                  └─┘    └────┘             
par                                 └─┘                  └─┘    └────┘             
pid                                                     └─┘                      
st                                 └───────────────────────────────────────────────┘
2021  | (b::l) (or.inr ain) pa := if pb : p b
id      └┘    └────┘            └┘      
src      └┘    └────┘            └┘
typ     └┘    └────┘            └┘      
2022      then by rw [filter_cons_of_pos _ pb]; apply mem_cons_of_mem; apply mem_filter_of_mem ain pa
id                   └────────────────┘   └┘         └─────────────┘        └───────────────┘ └─┘ └┘
src              └──┘└────────────────┘└─┘    └────┘└─────────────┘  └────┘                      
typ              └──┘└────────────────┘└─┘└┘  └────┘└─────────────┘  └────┘└───────────────┘└─┘└┘
doc              └──┘                  └─┘    └────┘                 └────┘                      
txt              └──┘                  └─┘    └────┘                 └────┘                      
par              └──┘                  └─┘    └────┘                 └────┘                      
pid                └┘                  └─┘                                                     
st              └──────────────────────────┘└───────────────────────────────────────────────────────
2023      else by rw [filter_cons_of_neg _ pb]; apply mem_filter_of_mem ain pa
id                   └────────────────┘   └┘         └───────────────┘ └─┘ └┘
src  ───┘        └──┘└────────────────┘└─┘    └────┘                      
typ  ───┘        └──┘└────────────────┘└─┘└┘  └────┘└───────────────┘└─┘└┘
doc  ───┘        └──┘                  └─┘    └────┘                      
txt  ───┘        └──┘                  └─┘    └────┘                      
par  ───┘        └──┘                  └─┘    └────┘                      
pid  ───┘          └┘                  └─┘                               
st   ───┘       └──────────────────────────┘└────────────────────────────────
2024  
src  
typ  
doc  
txt  
par  
pid  
st   
2025  @[simp] theorem mem_filter {a : α} {l} : a ∈ filter p l ↔ a ∈ l ∧ p a :=
id                                             └────┘         
src                                              └────┘           
typ                                            └────┘         
doc    └──┘
2026  ⟨λ h, ⟨mem_of_mem_filter h, of_mem_filter h⟩, λ ⟨h₁, h₂⟩, mem_filter_of_mem h₁ h₂⟩
id         └───────────────┘   └───────────┘      └┘  └┘   └───────────────┘
src         └───────────────┘    └───────────┘                 └───────────────┘
typ        └───────────────┘   └───────────┘      └┘  └┘   └───────────────┘
2027  
2028  theorem filter_eq_self {l} : filter p l = l ↔ ∀ a ∈ l, p a :=
id                                └────┘              
src                               └────┘        
typ                               └────┘              
2029  begin
st   └─────
2030    induction l with a l ih,
id               
src    └────────┘ └──────────┘
typ    └────────┘└──────────┘
doc    └────────┘ └──────────┘
txt    └────────┘ └──────────┘
par    └────────┘ └──────────┘
pid              └─────────┘
st   ────────────────────────┘└─
2031    { exact iff_of_true rfl (forall_mem_nil _) },
id             └─────────┘ └─┘  └────────────┘
src      └────┘└─────────┘└─┘ └────────────┘└──┘
typ      └────┘└─────────┘└─┘ └────────────┘└──┘
doc      └────┘                             └──┘
txt      └────┘                             └──┘
par      └────┘                             └──┘
pid                                        └─┘
st   ───┘└───────────────────────────────────────┘└┘
2032    rw forall_mem_cons, by_cases p a,
id        └─────────────┘            
src    └─┘└─────────────┘  └───────┘ 
typ    └─┘└─────────────┘  └───────┘
doc    └─┘                 └───────┘ 
txt    └─┘                 └───────┘ 
par    └─┘                 └───────┘ 
pid                                
st   ───────────────────┘└────────────┘└─
2033    { rw [filter_cons_of_pos _ h, cons_inj', ih, and_iff_right h] },
id           └────────────────┘     └───────┘  └┘  └───────────┘ 
src      └──┘└────────────────┘└─┘ └┘└───────┘└┘  └┘└───────────┘ └┘
typ      └──┘└────────────────┘└─┘└┘└───────┘└┘└┘└┘└───────────┘└┘
doc      └──┘                  └─┘ └┘         └┘  └┘              └┘
txt      └──┘                  └─┘ └┘         └┘  └┘              └┘
par      └──┘                  └─┘ └┘         └┘  └┘              └┘
pid        └┘                  └─┘ └┘         └┘  └┘              
st   ───┘└────────────────────────┘└─────────┘└──┘└───────────────┘└┘
2034    { rw [filter_cons_of_neg _ h],
id           └────────────────┘   
src      └──┘└────────────────┘└─┘ 
typ      └──┘└────────────────┘└─┘
doc      └──┘                  └─┘ 
txt      └──┘                  └─┘ 
par      └──┘                  └─┘ 
pid        └┘                  └─┘ 
st   ─────────────────────────────┘└──
2035      refine iff_of_false _ (mt and.left h), intro e,
id              └──────────┘    └┘ └──────┘ 
src      └─────┘└──────────┘└─┘ └┘└──────┘   └─────┘
typ      └─────┘└──────────┘└─┘ └┘└──────┘  └─────┘
doc      └─────┘            └─┘              └─────┘
txt      └─────┘            └─┘              └─────┘
par      └─────┘            └─┘              └─────┘
pid                        └─┘                   └┘
st   ────────────────────────────────────────┘└───────┘└─
2036      have := filter_sublist l, rw e at this,
id               └────────────┘      
src      └──────┘└────────────┘   └─┘ └──────┘
typ      └──────┘└────────────┘  └─┘└──────┘
doc      └──────┘                 └─┘ └──────┘
txt      └──────┘                 └─┘ └──────┘
par      └──────┘                 └─┘ └──────┘
pid      └───┘└─┘                    └──────┘
st   ───────────────────────────┘└────────────┘└─
2037      exact not_lt_of_ge (length_le_of_sublist this) (lt_succ_self _) }
id             └──────────┘  └──────────────────┘ └──┘   └──────────┘
src      └────┘└──────────┘ └──────────────────┘    └┘ └──────────┘└──┘
typ      └────┘└──────────┘ └──────────────────┘└──┘└┘ └──────────┘└──┘
doc      └────┘                                     └┘             └──┘
txt      └────┘                                     └┘             └──┘
par      └────┘                                     └┘             └──┘
pid                                                └┘             └─┘
st   ───────────────────────────────────────────────────────────────────┘└─
2038  end
st   ──┘
2039  
2040  theorem filter_eq_nil {l} : filter p l = [] ↔ ∀ a ∈ l, ¬p a :=
id                               └────┘    └┘          
src                              └────┘      └┘           
typ                              └────┘    └┘          
2041  by simp only [eq_nil_iff_forall_not_mem, mem_filter, not_and]
id                 └───────────────────────┘  └────────┘  └─────┘
src     └─────────┘└───────────────────────┘└┘└────────┘└┘└─────┘└─
typ     └─────────┘└───────────────────────┘└┘└────────┘└┘└─────┘└─
doc     └─────────┘                         └┘          └┘       └─
txt     └─────────┘                         └┘          └┘       └─
par     └─────────┘                         └┘          └┘       └─
pid         └──┘└┘                         └┘          └┘       
st     └───────────────────────────────────────────────────────────
2042  
src  
typ  
doc  
txt  
par  
pid  
st   
2043  theorem filter_sublist_filter {l₁ l₂} (s : l₁ <+ l₂) : filter p l₁ <+ filter p l₂ :=
id                                              └┘ └┘ └┘    └────┘  └┘ └┘ └────┘  └┘
src                                                └┘       └────┘      └┘ └────┘
typ                                             └┘ └┘ └┘    └────┘  └┘ └┘ └────┘  └┘
2044  by rw ← filter_map_eq_filter; exact filter_map_sublist_filter_map _ s
id           └──────────────────┘        └───────────────────────────┘   
src     └───┘└──────────────────┘  └────┘└───────────────────────────┘└─┘ 
typ     └───┘└──────────────────┘  └────┘└───────────────────────────┘└─┘
doc     └───┘                      └────┘                             └─┘ 
txt     └───┘                      └────┘                             └─┘ 
par     └───┘                      └────┘                             └─┘ 
pid       └─┘                                                        └─┘ 
st     └───────────────────────────────────────────────────────────────────
2045  
src  
typ  
doc  
txt  
par  
pid  
st   
2046  theorem filter_of_map (f : β → α) (l) : filter p (map f l) = map f (filter (p ∘ f) l) :=
id                                         └────┘   └─┘     └─┘   └────┘      
src                                          └────┘    └─┘       └─┘    └────┘    
typ                                        └────┘   └─┘     └─┘   └────┘      
2047  by rw [← filter_map_eq_map, filter_filter_map, filter_map_filter]; refl
id            └───────────────┘  └───────────────┘  └───────────────┘
src     └────┘└───────────────┘└┘└───────────────┘└┘└───────────────┘  └────
typ     └────┘└───────────────┘└┘└───────────────┘└┘└───────────────┘  └────
doc     └────┘                 └┘                 └┘                   └────
txt     └────┘                 └┘                 └┘                   └────
par     └────┘                 └┘                 └┘                   └────
pid       └──┘                 └┘                 └┘                       
st     └──────────────────────┘└─────────────────┘└─────────────────┘└──────
2048  
src  
typ  
doc  
txt  
par  
pid  
st   
2049  @[simp] theorem filter_filter {q} [decidable_pred q] : ∀ l,
id                                      └────────────┘       
src                                     └────────────┘
typ                                     └────────────┘       
doc    └──┘
2050    filter p (filter q l) = filter (λ a, p a ∧ q a) l
id     └────┘   └────┘     └────┘            
src    └────┘    └────┘       └────┘           
typ    └────┘   └────┘     └────┘            
2051  | [] := rfl
id     └┘    └─┘
src    └┘    └─┘
typ    └┘    └─┘
2052  | (a :: l) := by by_cases hp : p a; by_cases hq : q a; simp only [hp, hq, filter, if_true, if_false,
id        └┘                                                       └┘  └┘  └────┘  └─────┘  └──────┘
src       └┘          └───────┘  └─┘    └───────┘  └─┘    └─────────┘  └┘  └┘└────┘└┘└─────┘└┘└──────┘└─
typ       └┘          └───────┘  └─┘  └───────┘  └─┘  └─────────┘└┘└┘└┘└┘└────┘└┘└─────┘└┘└──────┘└─
doc                   └───────┘  └─┘    └───────┘  └─┘    └─────────┘  └┘  └┘      └┘       └┘        └─
txt                   └───────┘  └─┘    └───────┘  └─┘    └─────────┘  └┘  └┘      └┘       └┘        └─
par                   └───────┘  └─┘    └───────┘  └─┘    └─────────┘  └┘  └┘      └┘       └┘        └─
pid                             └─┘              └─┘        └──┘└┘  └┘  └┘      └┘       └┘        └─
st                   └────────────────────────────────────────────────────────────────────────────────────
2053      true_and, false_and, filter_filter l, eq_self_iff_true]
id       └──────┘  └───────┘  └───────────┘   └──────────────┘
src  ───┘└──────┘└┘└───────┘└┘              └┘└──────────────┘└─
typ  ───┘└──────┘└┘└───────┘└┘└───────────┘└┘└──────────────┘└─
doc  ───┘        └┘         └┘              └┘                └─
txt  ───┘        └┘         └┘              └┘                └─
par  ───┘        └┘         └┘              └┘                └─
pid  ───┘        └┘         └┘              └┘                
st   ────────────────────────────────────────────────────────────
2054  
src  
typ  
doc  
txt  
par  
pid  
st   
2055  @[simp] lemma filter_true {h : decidable_pred (λ a : α, true)} (l : list α) : @filter α (λ _, true) h l = l :=
id                                  └────────────┘          └──┘        └──┘      └────┘       └──┘     
src                                 └────────────┘           └──┘        └──┘       └────┘         └──┘      
typ                                 └────────────┘          └──┘        └──┘      └────┘       └──┘     
doc    └──┘
2056  by convert filter_eq_self.2 (λ _ _, trivial)
id              └────────────┘           └─────┘
src     └──────┘└────────────┘└─┘  └────┘└─────┘└─
typ     └──────┘└────────────┘└─┘  └────┘└─────┘└─
doc     └──────┘              └─┘  └────┘       └─
txt     └──────┘              └─┘  └────┘       └─
par     └──────┘              └─┘  └────┘       └─
pid                          └─┘  └────┘       
st     └──────────────────────────────────────────
2057  
src  
typ  
doc  
txt  
par  
pid  
st   
2058  @[simp] lemma filter_false {h : decidable_pred (λ a : α, false)} (l : list α) : @filter α (λ _, false) h l = [] :=
id                                   └────────────┘          └───┘        └──┘      └────┘       └───┘     └┘
src                                  └────────────┘           └───┘        └──┘       └────┘         └───┘       └┘
typ                                  └────────────┘          └───┘        └──┘      └────┘       └───┘     └┘
doc    └──┘
2059  by convert filter_eq_nil.2 (λ _ _, id)
id              └───────────┘           └┘
src     └──────┘└───────────┘└─┘  └────┘└┘└─
typ     └──────┘└───────────┘└─┘  └────┘└┘└─
doc     └──────┘             └─┘  └────┘  └─
txt     └──────┘             └─┘  └────┘  └─
par     └──────┘             └─┘  └────┘  └─
pid                         └─┘  └────┘  
st     └────────────────────────────────────
2060  
src  
typ  
doc  
txt  
par  
pid  
st   
2061  @[simp] theorem span_eq_take_drop (p : α → Prop) [decidable_pred p] : ∀ (l : list α), span p l = (take_while p l, drop_while p l)
id                                                    └────────────┘           └──┘    └──┘    └────────┘    └────────┘  
src                                                    └────────────┘             └──┘     └──┘      └────────┘      └────────┘
typ                                                   └────────────┘           └──┘    └──┘    └────────┘    └────────┘  
doc    └──┘                                                                                            └────────┘
2062  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
2063  | (a::l) := if pa : p a then by simp only [span, if_pos pa, span_eq_take_drop l, take_while, drop_while]
id      └┘      └┘                            └──┘  └────┘ └┘  └───────────────┘   └────────┘  └────────┘
src      └┘      └┘                  └─────────┘└──┘└┘└────┘  └┘                  └┘└────────┘└┘└────────┘└─
typ     └┘      └┘                 └─────────┘└──┘└┘└────┘└┘└┘└───────────────┘└┘└────────┘└┘└────────┘└─
doc                                  └─────────┘    └┘        └┘                  └┘└────────┘└┘          └─
txt                                  └─────────┘    └┘        └┘                  └┘          └┘          └─
par                                  └─────────┘    └┘        └┘                  └┘          └┘          └─
pid                                      └──┘└┘    └┘        └┘                  └┘          └┘          
st                                  └─────────────────────────────────────────────────────────────────────────
2064      else by simp only [span, take_while, drop_while, if_neg pa]
id                          └──┘  └────────┘  └────────┘  └────┘ └┘
src  ───┘        └─────────┘└──┘└┘└────────┘└┘└────────┘└┘└────┘  └─
typ  ───┘        └─────────┘└──┘└┘└────────┘└┘└────────┘└┘└────┘└┘└─
doc  ───┘        └─────────┘    └┘└────────┘└┘          └┘        └─
txt  ───┘        └─────────┘    └┘          └┘          └┘        └─
par  ───┘        └─────────┘    └┘          └┘          └┘        └─
pid  ───┘            └──┘└┘    └┘          └┘          └┘        
st   ───┘       └────────────────────────────────────────────────────
2065  
src  
typ  
doc  
txt  
par  
pid  
st   
2066  @[simp] theorem take_while_append_drop (p : α → Prop) [decidable_pred p] : ∀ (l : list α), take_while p l ++ drop_while p l = l
id                                                         └────────────┘           └──┘    └────────┘   └┘ └────────┘    
src                                                         └────────────┘             └──┘     └────────┘     └┘ └────────┘     
typ                                                        └────────────┘           └──┘    └────────┘   └┘ └────────┘    
doc    └──┘                                                                                     └────────┘
2067  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
2068  | (a::l) := if pa : p a then by rw [take_while, drop_while, if_pos pa, if_pos pa, cons_append, take_while_append_drop l]
id      └┘      └┘                     └────────┘  └────────┘  └────┘ └┘  └────┘ └┘  └─────────┘  └────────────────────┘ 
src      └┘      └┘                  └──┘└────────┘└┘└────────┘└┘└────┘  └┘└────┘  └┘└─────────┘└┘                       └─
typ     └┘      └┘                 └──┘└────────┘└┘└────────┘└┘└────┘└┘└┘└────┘└┘└┘└─────────┘└┘└────────────────────┘└─
doc                                  └──┘└────────┘└┘          └┘        └┘        └┘           └┘                       └─
txt                                  └──┘          └┘          └┘        └┘        └┘           └┘                       └─
par                                  └──┘          └┘          └┘        └┘        └┘           └┘                       └─
pid                                    └┘          └┘          └┘        └┘        └┘           └┘                       
st                                  └─────────────┘└──────────┘└─────────┘└─────────┘└───────────┘└────────────────────────┘
2069      else by rw [take_while, drop_while, if_neg pa, if_neg pa, nil_append]
id                   └────────┘  └────────┘  └────┘ └┘  └────┘ └┘  └────────┘
src  ───┘        └──┘└────────┘└┘└────────┘└┘└────┘  └┘└────┘  └┘└────────┘└─
typ  ───┘        └──┘└────────┘└┘└────────┘└┘└────┘└┘└┘└────┘└┘└┘└────────┘└─
doc  ───┘        └──┘└────────┘└┘          └┘        └┘        └┘          └─
txt  ───┘        └──┘          └┘          └┘        └┘        └┘          └─
par  ───┘        └──┘          └┘          └┘        └┘        └┘          └─
pid  ───┘          └┘          └┘          └┘        └┘        └┘          
st   ───┘       └─────────────┘└──────────┘└─────────┘└─────────┘└──────────┘
2070  
src  
typ  
doc  
txt  
par  
pid  
st   
2071  @[simp] theorem countp_nil (p : α → Prop) [decidable_pred p] : countp p [] = 0 := rfl
id                                             └────────────┘     └────┘  └┘       └─┘
src                                             └────────────┘      └────┘   └┘       └─┘
typ                                            └────────────┘     └────┘  └┘       └─┘
doc    └──┘                                                         └────┘
2072  
2073  @[simp] theorem countp_cons_of_pos {a : α} (l) (pa : p a) : countp p (a::l) = countp p l + 1 :=
id                                                            └────┘   └┘   └────┘   
src                                                              └────┘     └┘    └────┘     
typ                                                           └────┘   └┘   └────┘   
doc    └──┘                                                      └────┘            └────┘
2074  if_pos pa
id   └────┘ └┘
src  └────┘
typ  └────┘ └┘
2075  
2076  @[simp] theorem countp_cons_of_neg {a : α} (l) (pa : ¬ p a) : countp p (a::l) = countp p l :=
id                                                             └────┘   └┘   └────┘  
src                                                               └────┘     └┘    └────┘
typ                                                            └────┘   └┘   └────┘  
doc    └──┘                                                        └────┘            └────┘
2077  if_neg pa
id   └────┘ └┘
src  └────┘
typ  └────┘ └┘
2078  
2079  theorem countp_eq_length_filter (l) : countp p l = length (filter p l) :=
id                                         └────┘    └────┘  └────┘  
src                                        └────┘      └────┘  └────┘
typ                                        └────┘    └────┘  └────┘  
doc                                        └────┘
2080  by induction l with x l ih; [refl, by_cases (p x)]; [simp only [filter_cons_of_pos _ h, countp, ih, if_pos h],
id                                                              └────────────────┘     └────┘  └┘  └────┘ 
src     └────────┘ └──────────┘  └──┘  └───────┘      └─────────┘└────────────────┘└─┘ └┘└────┘└┘  └┘└────┘ 
typ     └────────┘└──────────┘  └──┘  └───────┘    └─────────┘└────────────────┘└─┘└┘└────┘└┘└┘└┘└────┘
doc     └────────┘ └──────────┘   └──┘  └───────┘       └─────────┘                  └─┘ └┘└────┘└┘  └┘       
txt     └────────┘ └──────────┘   └──┘  └───────┘       └─────────┘                  └─┘ └┘      └┘  └┘       
par     └────────┘ └──────────┘   └──┘  └───────┘       └─────────┘                  └─┘ └┘      └┘  └┘       
pid               └─────────┘                            └──┘└┘                  └─┘ └┘      └┘  └┘       
st     └────────────────────────────────────────────────────────────────────────────────────────────────────────────
2081    simp only [countp_cons_of_neg _ h, ih, filter_cons_of_neg _ h]]; refl
id                └────────────────┘     └┘  └────────────────┘   
src    └─────────┘└────────────────┘└─┘ └┘  └┘└────────────────┘└─┘    └───┘
typ    └─────────┘└────────────────┘└─┘└┘└┘└┘└────────────────┘└─┘   └───┘
doc    └─────────┘                  └─┘ └┘  └┘                  └─┘    └───┘
txt    └─────────┘                  └─┘ └┘  └┘                  └─┘    └───┘
par    └─────────┘                  └─┘ └┘  └┘                  └─┘    └───┘
pid        └──┘└┘                  └─┘ └┘  └┘                  └─┘        
st   ───────────────────────────────────────────────────────────────────────┘
2082  local attribute [simp] countp_eq_length_filter
id                          └─────────────────────┘
src                         └─────────────────────┘
typ                         └─────────────────────┘
doc                   └──┘
2083  
2084  @[simp] theorem countp_append (l₁ l₂) : countp p (l₁ ++ l₂) = countp p l₁ + countp p l₂ :=
id                                           └────┘   └┘ └┘ └┘   └────┘  └┘  └────┘  └┘
src                                          └────┘       └┘      └────┘       └────┘
typ                                          └────┘   └┘ └┘ └┘   └────┘  └┘  └────┘  └┘
doc    └──┘                                  └────┘                └────┘        └────┘
2085  by simp only [countp_eq_length_filter, filter_append, length_append]
id                 └─────────────────────┘  └───────────┘  └───────────┘
src     └─────────┘└─────────────────────┘└┘└───────────┘└┘└───────────┘└─
typ     └─────────┘└─────────────────────┘└┘└───────────┘└┘└───────────┘└─
doc     └─────────┘                       └┘             └┘             └─
txt     └─────────┘                       └┘             └┘             └─
par     └─────────┘                       └┘             └┘             └─
pid         └──┘└┘                       └┘             └┘             
st     └──────────────────────────────────────────────────────────────────
2086  
src  
typ  
doc  
txt  
par  
pid  
st   
2087  theorem countp_pos {l} : 0 < countp p l ↔ ∃ a ∈ l, p a :=
id                               └────┘          
src                              └────┘            
typ                              └────┘          
doc                               └────┘
2088  by simp only [countp_eq_length_filter, length_pos_iff_exists_mem, mem_filter, exists_prop]
id                 └─────────────────────┘  └───────────────────────┘  └────────┘  └─────────┘
src     └─────────┘└─────────────────────┘└┘└───────────────────────┘└┘└────────┘└┘└─────────┘└─
typ     └─────────┘└─────────────────────┘└┘└───────────────────────┘└┘└────────┘└┘└─────────┘└─
doc     └─────────┘                       └┘                         └┘          └┘           └─
txt     └─────────┘                       └┘                         └┘          └┘           └─
par     └─────────┘                       └┘                         └┘          └┘           └─
pid         └──┘└┘                       └┘                         └┘          └┘           
st     └────────────────────────────────────────────────────────────────────────────────────────
2089  
src  
typ  
doc  
txt  
par  
pid  
st   
2090  theorem countp_le_of_sublist {l₁ l₂} (s : l₁ <+ l₂) : countp p l₁ ≤ countp p l₂ :=
id                                             └┘ └┘ └┘    └────┘  └┘  └────┘  └┘
src                                               └┘       └────┘       └────┘
typ                                            └┘ └┘ └┘    └────┘  └┘  └────┘  └┘
doc                                                        └────┘        └────┘
2091  by simpa only [countp_eq_length_filter] using length_le_of_sublist (filter_sublist_filter s)
id                  └─────────────────────┘        └──────────────────┘  └───────────────────┘ 
src     └──────────┘└─────────────────────┘└──────┘└──────────────────┘ └───────────────────┘ └─
typ     └──────────┘└─────────────────────┘└──────┘└──────────────────┘ └───────────────────┘└─
doc     └──────────┘                       └──────┘                                           └─
txt     └──────────┘                       └──────┘                                           └─
par     └──────────┘                       └──────┘                                           └─
pid          └──┘└┘                       └────┘                                           
st     └──────────────────────────────────────────────────────────────────────────────────────────
2092  
src  
typ  
doc  
txt  
par  
pid  
st   
2093  @[simp] theorem countp_filter {q} [decidable_pred q] (l : list α) :
id                                      └────────────┘        └──┘ 
src                                     └────────────┘         └──┘
typ                                     └────────────┘        └──┘ 
doc    └──┘
2094    countp p (filter q l) = countp (λ a, p a ∧ q a) l :=
id     └────┘   └────┘     └────┘            
src    └────┘    └────┘       └────┘           
typ    └────┘   └────┘     └────┘            
doc    └────┘                  └────┘
2095  by simp only [countp_eq_length_filter, filter_filter]
id                 └─────────────────────┘  └───────────┘
src     └─────────┘└─────────────────────┘└┘└───────────┘└─
typ     └─────────┘└─────────────────────┘└┘└───────────┘└─
doc     └─────────┘                       └┘             └─
txt     └─────────┘                       └┘             └─
par     └─────────┘                       └┘             └─
pid         └──┘└┘                       └┘             
st     └───────────────────────────────────────────────────
2096  
src  
typ  
doc  
txt  
par  
pid  
st   
2097  end filter
2098  
2099  /- count -/
2100  
2101  section count
2102  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
2103  
2104  @[simp] theorem count_nil (a : α) : count a [] = 0 := rfl
id                                      └───┘  └┘       └─┘
src                                      └───┘   └┘       └─┘
typ                                     └───┘  └┘       └─┘
doc    └──┘                              └───┘
2105  
2106  theorem count_cons (a b : α) (l : list α) :
id                                    └──┘ 
src                                    └──┘
typ                                   └──┘ 
2107    count a (b :: l) = if a = b then succ (count a l) else count a l := rfl
id     └───┘    └┘               └──┘  └───┘         └───┘      └─┘
src    └───┘      └┘                  └──┘  └───┘           └───┘        └─┘
typ    └───┘    └┘               └──┘  └───┘         └───┘      └─┘
doc    └───┘                                  └───┘           └───┘
2108  
2109  theorem count_cons' (a b : α) (l : list α) :
id                                     └──┘ 
src                                     └──┘
typ                                    └──┘ 
2110    count a (b :: l) = count a l + (if a = b then 1 else 0) :=
id     └───┘    └┘    └───┘          
src    └───┘      └┘     └───┘            
typ    └───┘    └┘    └───┘          
doc    └───┘              └───┘
2111  begin rw count_cons, split_ifs; refl end
id            └────────┘
src        └─┘└────────┘  └───────┘  └───┘
typ        └─┘└────────┘  └───────┘  └───┘
doc        └─┘            └───────┘  └───┘
txt        └─┘            └───────┘  └───┘
par        └─┘            └───────┘  └───┘
pid                                     
st   └─────────────────┘└────────────────┘└─┘
2112  
2113  @[simp] theorem count_cons_self (a : α) (l : list α) : count a (a::l) = succ (count a l) :=
id                                               └──┘     └───┘   └┘   └──┘  └───┘  
src                                               └──┘      └───┘     └┘    └──┘  └───┘
typ                                              └──┘     └───┘   └┘   └──┘  └───┘  
doc    └──┘                                                 └───┘                  └───┘
2114  if_pos rfl
id   └────┘ └─┘
src  └────┘ └─┘
typ  └────┘ └─┘
2115  
2116  @[simp] theorem count_cons_of_ne {a b : α} (h : a ≠ b) (l : list α) : count a (b::l) = count a l :=
id                                                           └──┘     └───┘   └┘   └───┘  
src                                                             └──┘      └───┘     └┘    └───┘
typ                                                          └──┘     └───┘   └┘   └───┘  
doc    └──┘                                                                └───┘            └───┘
2117  if_neg h
id   └────┘ 
src  └────┘
typ  └────┘ 
2118  
2119  theorem count_tail : Π (l : list α) (a : α) (h : 0 < l.length),
id                              └──┘                  └─────┘
src                              └──┘                     └─────┘
typ                             └──┘                  └─────┘
2120    l.tail.count a = l.count a - ite (a = list.nth_le l 0 h) 1 0
id     └───┘└────┘   └────┘   └─┘    └─────────┘    
src     └───┘└────┘     └────┘    └─┘     └─────────┘
typ    └───┘└────┘   └────┘   └─┘    └─────────┘    
doc          └────┘      └────┘
2121  | (_ :: _) a h := by { rw [count_cons], split_ifs; simp }
id        └┘                    └────────┘
src       └┘                └──┘└────────┘  └───────┘  └───┘
typ       └┘                └──┘└────────┘  └───────┘  └───┘
doc                         └──┘            └───────┘  └───┘
txt                         └──┘            └───────┘  └───┘
par                         └──┘            └───────┘  └───┘
pid                           └┘                           
st                       └───────────────┘└─────────────────┘└┘
2122  
2123  theorem count_le_of_sublist (a : α) {l₁ l₂} : l₁ <+ l₂ → count a l₁ ≤ count a l₂ :=
id                                                └┘ └┘ └┘   └───┘  └┘  └───┘  └┘
src                                                   └┘      └───┘       └───┘
typ                                               └┘ └┘ └┘   └───┘  └┘  └───┘  └┘
doc                                                           └───┘        └───┘
2124  countp_le_of_sublist
id   └──────────────────┘
src  └──────────────────┘
typ  └──────────────────┘
2125  
2126  theorem count_le_count_cons (a b : α) (l : list α) : count a l ≤ count a (b :: l) :=
id                                             └──┘     └───┘    └───┘    └┘ 
src                                             └──┘      └───┘      └───┘      └┘
typ                                            └──┘     └───┘    └───┘    └┘ 
doc                                                       └───┘       └───┘
2127  count_le_of_sublist _ (sublist_cons _ _)
id   └─────────────────┘    └──────────┘
src  └─────────────────┘    └──────────┘
typ  └─────────────────┘    └──────────┘
2128  
2129  theorem count_singleton (a : α) : count a [a] = 1 := if_pos rfl
id                                    └───┘         └────┘ └─┘
src                                    └───┘           └────┘ └─┘
typ                                   └───┘         └────┘ └─┘
doc                                    └───┘
2130  
2131  @[simp] theorem count_append (a : α) : ∀ l₁ l₂, count a (l₁ ++ l₂) = count a l₁ + count a l₂ :=
id                                           └┘ └┘  └───┘   └┘ └┘ └┘   └───┘  └┘  └───┘  └┘
src                                                  └───┘       └┘      └───┘       └───┘
typ                                          └┘ └┘  └───┘   └┘ └┘ └┘   └───┘  └┘  └───┘  └┘
doc    └──┘                                          └───┘                └───┘        └───┘
2132  countp_append
id   └───────────┘
src  └───────────┘
typ  └───────────┘
2133  
2134  @[simp] theorem count_concat (a : α) (l : list α) : count a (concat l a) = succ (count a l) :=
id                                            └──┘     └───┘   └────┘     └──┘  └───┘  
src                                            └──┘      └───┘    └────┘       └──┘  └───┘
typ                                           └──┘     └───┘   └────┘     └──┘  └───┘  
doc    └──┘                                              └───┘    └────┘              └───┘
2135  by rw [concat_eq_append, count_append, count_singleton]
id          └──────────────┘  └──────────┘  └─────────────┘
src     └──┘└──────────────┘└┘└──────────┘└┘└─────────────┘└─
typ     └──┘└──────────────┘└┘└──────────┘└┘└─────────────┘└─
doc     └──┘                └┘            └┘               └─
txt     └──┘                └┘            └┘               └─
par     └──┘                └┘            └┘               └─
pid       └┘                └┘            └┘               
st     └───────────────────┘└────────────┘└───────────────┘
2136  
src  
typ  
doc  
txt  
par  
pid  
st   
2137  theorem count_pos {a : α} {l : list α} : 0 < count a l ↔ a ∈ l :=
id                                 └──┘        └───┘      
src                                 └──┘         └───┘        
typ                                └──┘        └───┘      
doc                                               └───┘
2138  by simp only [count, countp_pos, exists_prop, exists_eq_right']
id                 └───┘  └────────┘  └─────────┘  └──────────────┘
src     └─────────┘└───┘└┘└────────┘└┘└─────────┘└┘└──────────────┘└─
typ     └─────────┘└───┘└┘└────────┘└┘└─────────┘└┘└──────────────┘└─
doc     └─────────┘└───┘└┘          └┘           └┘                └─
txt     └─────────┘     └┘          └┘           └┘                └─
par     └─────────┘     └┘          └┘           └┘                └─
pid         └──┘└┘     └┘          └┘           └┘                
st     └─────────────────────────────────────────────────────────────
2139  
src  
typ  
doc  
txt  
par  
pid  
st   
2140  @[simp] theorem count_eq_zero_of_not_mem {a : α} {l : list α} (h : a ∉ l) : count a l = 0 :=
id                                                        └──┘              └───┘   
src                                                        └──┘                 └───┘     
typ                                                       └──┘              └───┘   
doc    └──┘                                                                      └───┘
2141  by_contradiction $ λ h', h $ count_pos.1 (nat.pos_of_ne_zero h')
id   └──────────────┘     └┘     └───────┘   └────────────────┘ └┘
src  └──────────────┘             └───────┘   └────────────────┘
typ  └──────────────┘     └┘     └───────┘   └────────────────┘ └┘
2142  
2143  theorem not_mem_of_count_eq_zero {a : α} {l : list α} (h : count a l = 0) : a ∉ l :=
id                                                └──┘        └───┘           
src                                                └──┘         └───┘             
typ                                               └──┘        └───┘           
doc                                                             └───┘
2144  λ h', ne_of_gt (count_pos.2 h') h
id     └┘  └──────┘  └───────┘  └┘  
src        └──────┘  └───────┘
typ    └┘  └──────┘  └───────┘  └┘  
2145  
2146  @[simp] theorem count_repeat (a : α) (n : ℕ) : count a (repeat a n) = n :=
id                                                └───┘   └────┘     
src                                                └───┘    └────┘      
typ                                               └───┘   └────┘     
doc    └──┘                                         └───┘
2147  by rw [count, countp_eq_length_filter, filter_eq_self.2, length_repeat];
id          └───┘  └─────────────────────┘  └────────────┘    └───────────┘
src     └──┘└───┘└┘└─────────────────────┘└┘└────────────┘└──┘└───────────┘
typ     └──┘└───┘└┘└─────────────────────┘└┘└────────────┘└──┘└───────────┘
doc     └──┘└───┘└┘                       └┘              └──┘             
txt     └──┘     └┘                       └┘              └──┘             
par     └──┘     └┘                       └┘              └──┘             
pid       └┘     └┘                       └┘              └──┘             
st     └────────┘└───────────────────────┘└──────────────┘└───────────────┘└─
2148     exact λ b m, (eq_of_mem_repeat m).symm
id                    └──────────────┘
src     └────┘ └────┘ └──────────────┘ └──────
typ     └────┘ └────┘ └──────────────┘ └──────
doc     └────┘ └────┘                  └──────
txt     └────┘ └────┘                  └──────
par     └────┘ └────┘                  └──────
pid           └────┘                  └───┘└─
st   ──────────────────────────────────────────
2149  
src  
typ  
doc  
txt  
par  
pid  
st   
2150  theorem le_count_iff_repeat_sublist {a : α} {l : list α} {n : ℕ} : n ≤ count a l ↔ repeat a n <+ l :=
id                                                   └──┘              └───┘    └────┘   └┘ 
src                                                   └──┘                └───┘      └────┘     └┘
typ                                                  └──┘              └───┘    └────┘   └┘ 
doc                                                                         └───┘
2151  ⟨λ h, ((repeat_sublist_repeat a).2 h).trans $
id          └───────────────────┘     └───┘
src          └───────────────────┘       └───┘
typ         └───────────────────┘     └───┘
2152    have filter (eq a) l = repeat a (count a l), from eq_repeat.2
id          └────┘  └┘     └────┘   └───┘          └───────┘
src         └────┘  └┘       └────┘    └───┘            └───────┘
typ         └────┘  └┘     └────┘   └───┘          └───────┘
doc                                     └───┘
2153      ⟨by simp only [count, countp_eq_length_filter], λ b m, (of_mem_filter m).symm⟩,
id                      └───┘  └─────────────────────┘         └───────────┘  └──┘
src          └─────────┘└───┘└┘└─────────────────────┘          └───────────┘   └──┘
typ          └─────────┘└───┘└┘└─────────────────────┘        └───────────┘  └──┘
doc          └─────────┘└───┘└┘                       
txt          └─────────┘     └┘                       
par          └─────────┘     └┘                       
pid              └──┘└┘     └┘                       
st          └─────────────────────────────────────────┘
2154    by rw ← this; apply filter_sublist,
id             └──┘        └────────────┘
src       └───┘      └────┘└────────────┘
typ       └───┘└──┘  └────┘└────────────┘
doc       └───┘      └────┘
txt       └───┘      └────┘
par       └───┘      └────┘
pid         └─┘           
st       └──────────────────────────────┘
2155   λ h, by simpa only [count_repeat] using count_le_of_sublist a h⟩
id                       └──────────┘        └─────────────────┘  
src           └──────────┘└──────────┘└──────┘└─────────────────┘ 
typ          └──────────┘└──────────┘└──────┘└─────────────────┘
doc           └──────────┘            └──────┘                    
txt           └──────────┘            └──────┘                    
par           └──────────┘            └──────┘                    
pid                └──┘└┘            └────┘                    
st           └──────────────────────────────────────────────────────┘
2156  
2157  @[simp] theorem count_filter {p} [decidable_pred p]
id                                     └────────────┘ 
src                                    └────────────┘
typ                                    └────────────┘ 
doc    └──┘
2158    {a} {l : list α} (h : p a) : count a (filter p l) = count a l :=
id              └──┘             └───┘   └────┘     └───┘  
src             └──┘                └───┘    └────┘       └───┘
typ             └──┘             └───┘   └────┘     └───┘  
doc                                 └───┘                  └───┘
2159  by simp only [count, countp_filter]; congr; exact
id                 └───┘  └───────────┘
src     └─────────┘└───┘└┘└───────────┘  └───┘  └────┘
typ     └─────────┘└───┘└┘└───────────┘  └───┘  └────┘
doc     └─────────┘└───┘└┘                      └────┘
txt     └─────────┘     └┘               └───┘  └────┘
par     └─────────┘     └┘               └───┘  └────┘
pid         └──┘└┘     └┘                           
st     └───────────────────────────────────────────────
2160  set.ext (λ b, and_iff_left_of_imp (λ e, e ▸ h))
id   └─────┘       └─────────────────┘          
src  └─────┘  └──┘└─────────────────┘  └──┘  └──
typ  └─────┘  └──┘└─────────────────┘  └──┘ └──
doc           └──┘                     └──┘   └──
txt           └──┘                     └──┘   └──
par           └──┘                     └──┘   └──
pid           └──┘                     └──┘   └┘
st   ────────────────────────────────────────────────
2161  
src  
typ  
doc  
txt  
par  
pid  
st   
2162  end count
2163  
2164  /- prefix, suffix, infix -/
2165  
2166  @[simp] theorem prefix_append (l₁ l₂ : list α) : l₁ <+: l₁ ++ l₂ := ⟨l₂, rfl⟩
id                                          └──┘     └┘ └─┘ └┘ └┘ └┘     └┘  └─┘
src                                         └──┘         └─┘    └┘            └─┘
typ                                         └──┘     └┘ └─┘ └┘ └┘ └┘     └┘  └─┘
doc    └──┘                                              └─┘
2167  
2168  @[simp] theorem suffix_append (l₁ l₂ : list α) : l₂ <:+ l₁ ++ l₂ := ⟨l₁, rfl⟩
id                                          └──┘     └┘ └─┘ └┘ └┘ └┘     └┘  └─┘
src                                         └──┘         └─┘    └┘            └─┘
typ                                         └──┘     └┘ └─┘ └┘ └┘ └┘     └┘  └─┘
doc    └──┘                                              └─┘
2169  
2170  @[simp] theorem infix_append (l₁ l₂ l₃ : list α) : l₂ <:+: l₁ ++ l₂ ++ l₃ := ⟨l₁, l₃, rfl⟩
id                                            └──┘     └┘ └──┘ └┘ └┘ └┘ └┘ └┘     └┘  └┘  └─┘
src                                           └──┘         └──┘    └┘    └┘                └─┘
typ                                           └──┘     └┘ └──┘ └┘ └┘ └┘ └┘ └┘     └┘  └┘  └─┘
doc    └──┘                                                └──┘
2171  
2172  theorem nil_prefix (l : list α) : [] <+: l := ⟨l, rfl⟩
id                           └──┘     └┘ └─┘        └─┘
src                          └──┘      └┘ └─┘          └─┘
typ                          └──┘     └┘ └─┘        └─┘
doc                                       └─┘
2173  
2174  theorem nil_suffix (l : list α) : [] <:+ l := ⟨l, append_nil _⟩
id                           └──┘     └┘ └─┘        └────────┘
src                          └──┘      └┘ └─┘          └────────┘
typ                          └──┘     └┘ └─┘        └────────┘
doc                                       └─┘
2175  
2176  @[refl] theorem prefix_refl (l : list α) : l <+: l := ⟨[], append_nil _⟩
id                                    └──┘      └─┘      └┘  └────────┘
src    └──┘                           └──┘        └─┘       └┘  └────────┘
typ                                   └──┘      └─┘      └┘  └────────┘
doc    └──┘                                       └─┘
2177  
2178  @[refl] theorem suffix_refl (l : list α) : l <:+ l := ⟨[], rfl⟩
id                                    └──┘      └─┘      └┘  └─┘
src    └──┘                           └──┘        └─┘       └┘  └─┘
typ                                   └──┘      └─┘      └┘  └─┘
doc    └──┘                                       └─┘
2179  
2180  @[simp] theorem suffix_cons (a : α) : ∀ l, l <:+ a :: l := suffix_append [a]
id                                             └─┘  └┘     └───────────┘ 
src                                               └─┘   └┘      └───────────┘  
typ                                            └─┘  └┘     └───────────┘ 
doc    └──┘                                       └─┘
2181  
2182  @[simp] theorem prefix_concat (a : α) (l) : l <+: concat l a :=
id                                               └─┘ └────┘  
src                                                └─┘ └────┘
typ                                              └─┘ └────┘  
doc    └──┘                                        └─┘ └────┘
2183  by simp only [concat_eq_append, prefix_append]
id                 └──────────────┘  └───────────┘
src     └─────────┘└──────────────┘└┘└───────────┘└─
typ     └─────────┘└──────────────┘└┘└───────────┘└─
doc     └─────────┘                └┘             └─
txt     └─────────┘                └┘             └─
par     └─────────┘                └┘             └─
pid         └──┘└┘                └┘             
st     └────────────────────────────────────────────
2184  
src  
typ  
doc  
txt  
par  
pid  
st   
2185  theorem infix_of_prefix {l₁ l₂ : list α} : l₁ <+: l₂ → l₁ <:+: l₂ :=
id                                    └──┘     └┘ └─┘ └┘   └┘ └──┘ └┘
src                                   └──┘         └─┘         └──┘
typ                                   └──┘     └┘ └─┘ └┘   └┘ └──┘ └┘
doc                                                └─┘         └──┘
2186  λ⟨t, h⟩, ⟨[], t, h⟩
id          └┘
src            └┘
typ         └┘
2187  
2188  theorem infix_of_suffix {l₁ l₂ : list α} : l₁ <:+ l₂ → l₁ <:+: l₂ :=
id                                    └──┘     └┘ └─┘ └┘   └┘ └──┘ └┘
src                                   └──┘         └─┘         └──┘
typ                                   └──┘     └┘ └─┘ └┘   └┘ └──┘ └┘
doc                                                └─┘         └──┘
2189  λ⟨t, h⟩, ⟨t, [], by simp only [h, append_nil]⟩
id              └┘                  └────────┘
src               └┘     └─────────┘ └┘└────────┘
typ             └┘     └─────────┘└┘└────────┘
doc                      └─────────┘ └┘          
txt                      └─────────┘ └┘          
par                      └─────────┘ └┘          
pid                          └──┘└┘ └┘          
st                      └────────────────────────┘
2190  
2191  @[refl] theorem infix_refl (l : list α) : l <:+: l := infix_of_prefix $ prefix_refl l
id                                   └──┘      └──┘     └─────────────┘   └─────────┘ 
src    └──┘                          └──┘        └──┘      └─────────────┘   └─────────┘
typ                                  └──┘      └──┘     └─────────────┘   └─────────┘ 
doc    └──┘                                      └──┘
2192  
2193  theorem nil_infix (l : list α) : [] <:+: l := infix_of_prefix $ nil_prefix l
id                          └──┘     └┘ └──┘     └─────────────┘   └────────┘ 
src                         └──┘      └┘ └──┘      └─────────────┘   └────────┘
typ                         └──┘     └┘ └──┘     └─────────────┘   └────────┘ 
doc                                      └──┘
2194  
2195  theorem infix_cons {L₁ L₂ : list α} {x : α} : L₁ <:+: L₂ → L₁ <:+: x :: L₂ :=
id                               └──┘            └┘ └──┘ └┘   └┘ └──┘  └┘ └┘
src                              └──┘                 └──┘         └──┘   └┘
typ                              └──┘            └┘ └──┘ └┘   └┘ └──┘  └┘ └┘
doc                                                   └──┘         └──┘
2196  λ⟨LP, LS, H⟩, ⟨x :: LP, LS, H ▸ rfl⟩
id    └┘  └┘       └┘            └─┘
src                   └┘            └─┘
typ   └┘  └┘       └┘            └─┘
2197  
2198  @[trans] theorem is_prefix.trans : ∀ {l₁ l₂ l₃ : list α}, l₁ <+: l₂ → l₂ <+: l₃ → l₁ <+: l₃
id                                                   └──┘    └┘ └─┘ └┘   └┘ └─┘ └┘   └┘ └─┘ └┘
src    └───┘                                          └──┘        └─┘         └─┘         └─┘
typ                                                  └──┘    └┘ └─┘ └┘   └┘ └─┘ └┘   └┘ └─┘ └┘
doc    └───┘                                                      └─┘         └─┘         └─┘
2199  | l ._ ._ ⟨r₁, rfl⟩ ⟨r₂, rfl⟩ := ⟨r₁ ++ r₂, (append_assoc _ _ _).symm⟩
id              └┘        └┘  └─┘         └┘      └──────────┘       └──┘
src                           └─┘         └┘      └──────────┘       └──┘
typ             └┘        └┘  └─┘         └┘      └──────────┘       └──┘
2200  
2201  @[trans] theorem is_suffix.trans : ∀ {l₁ l₂ l₃ : list α}, l₁ <:+ l₂ → l₂ <:+ l₃ → l₁ <:+ l₃
id                                                   └──┘    └┘ └─┘ └┘   └┘ └─┘ └┘   └┘ └─┘ └┘
src    └───┘                                          └──┘        └─┘         └─┘         └─┘
typ                                                  └──┘    └┘ └─┘ └┘   └┘ └─┘ └┘   └┘ └─┘ └┘
doc    └───┘                                                      └─┘         └─┘         └─┘
2202  | l ._ ._ ⟨l₁, rfl⟩ ⟨l₂, rfl⟩ := ⟨l₂ ++ l₁, append_assoc _ _ _⟩
id              └┘        └┘  └─┘         └┘     └──────────┘
src                           └─┘         └┘     └──────────┘
typ             └┘        └┘  └─┘         └┘     └──────────┘
2203  
2204  @[trans] theorem is_infix.trans : ∀ {l₁ l₂ l₃ : list α}, l₁ <:+: l₂ → l₂ <:+: l₃ → l₁ <:+: l₃
id                                                  └──┘    └┘ └──┘ └┘   └┘ └──┘ └┘   └┘ └──┘ └┘
src    └───┘                                         └──┘        └──┘         └──┘         └──┘
typ                                                 └──┘    └┘ └──┘ └┘   └┘ └──┘ └┘   └┘ └──┘ └┘
doc    └───┘                                                     └──┘         └──┘         └──┘
2205  | l ._ ._ ⟨l₁, r₁, rfl⟩ ⟨l₂, r₂, rfl⟩ := ⟨l₂ ++ l₁, r₁ ++ r₂, by simp only [append_assoc]⟩
id              └┘  └┘        └┘  └┘  └─┘         └┘        └┘                   └──────────┘
src                                   └─┘         └┘        └┘        └─────────┘└──────────┘
typ             └┘  └┘        └┘  └┘  └─┘         └┘        └┘        └─────────┘└──────────┘
doc                                                                   └─────────┘            
txt                                                                   └─────────┘            
par                                                                   └─────────┘            
pid                                                                       └──┘└┘            
st                                                                   └───────────────────────┘
2206  
2207  theorem sublist_of_infix {l₁ l₂ : list α} : l₁ <:+: l₂ → l₁ <+ l₂ :=
id                                     └──┘     └┘ └──┘ └┘   └┘ └┘ └┘
src                                    └──┘         └──┘         └┘
typ                                    └──┘     └┘ └──┘ └┘   └┘ └┘ └┘
doc                                                 └──┘
2208  λ⟨s, t, h⟩, by rw [← h]; exact (sublist_append_right _ _).trans (sublist_append_left _ _)
id                                 └──────────────────┘             └─────────────────┘
src                 └────┘   └────┘ └──────────────────┘└──────────┘ └─────────────────┘└─────
typ                └────┘  └────┘ └──────────────────┘└──────────┘ └─────────────────┘└─────
doc                 └────┘   └────┘                     └──────────┘                    └─────
txt                 └────┘   └────┘                     └──────────┘                    └─────
par                 └────┘   └────┘                     └──────────┘                    └─────
pid                   └──┘                             └──────────┘                    └───┘
st                 └──────┘└──────────────────────────────────────────────────────────────────
2209  
src  
typ  
doc  
txt  
par  
pid  
st   
2210  theorem sublist_of_prefix {l₁ l₂ : list α} : l₁ <+: l₂ → l₁ <+ l₂ :=
id                                      └──┘     └┘ └─┘ └┘   └┘ └┘ └┘
src                                     └──┘         └─┘         └┘
typ                                     └──┘     └┘ └─┘ └┘   └┘ └┘ └┘
doc                                                  └─┘
2211  sublist_of_infix ∘ infix_of_prefix
id   └──────────────┘  └─────────────┘
src  └──────────────┘  └─────────────┘
typ  └──────────────┘  └─────────────┘
2212  
2213  theorem sublist_of_suffix {l₁ l₂ : list α} : l₁ <:+ l₂ → l₁ <+ l₂ :=
id                                      └──┘     └┘ └─┘ └┘   └┘ └┘ └┘
src                                     └──┘         └─┘         └┘
typ                                     └──┘     └┘ └─┘ └┘   └┘ └┘ └┘
doc                                                  └─┘
2214  sublist_of_infix ∘ infix_of_suffix
id   └──────────────┘  └─────────────┘
src  └──────────────┘  └─────────────┘
typ  └──────────────┘  └─────────────┘
2215  
2216  theorem reverse_suffix {l₁ l₂ : list α} : reverse l₁ <:+ reverse l₂ ↔ l₁ <+: l₂ :=
id                                   └──┘     └─────┘ └┘ └─┘ └─────┘ └┘  └┘ └─┘ └┘
src                                  └──┘      └─────┘    └─┘ └─────┘        └─┘
typ                                  └──┘     └─────┘ └┘ └─┘ └─────┘ └┘  └┘ └─┘ └┘
doc                                                       └─┘                 └─┘
2217  ⟨λ ⟨r, e⟩, ⟨reverse r,
id             └─────┘
src              └─────┘
typ            └─────┘
2218    by rw [← reverse_reverse l₁, ← reverse_append, e, reverse_reverse]⟩,
id              └─────────────┘ └┘    └────────────┘    └─────────────┘
src       └────┘└─────────────┘  └──┘└────────────┘└┘ └┘└─────────────┘
typ       └────┘└─────────────┘└┘└──┘└────────────┘└┘└┘└─────────────┘
doc       └────┘                 └──┘              └┘ └┘               
txt       └────┘                 └──┘              └┘ └┘               
par       └────┘                 └──┘              └┘ └┘               
pid         └──┘                 └──┘              └┘ └┘               
st       └───────────────────────┘└────────────────┘└─┘└───────────────┘
2219   λ ⟨r, e⟩, ⟨reverse r, by rw [← reverse_append, e]⟩⟩
id             └─────┘             └────────────┘  
src              └─────┘       └────┘└────────────┘└┘ 
typ            └─────┘       └────┘└────────────┘└┘
doc                            └────┘              └┘ 
txt                            └────┘              └┘ 
par                            └────┘              └┘ 
pid                              └──┘              └┘ 
st                            └───────────────────┘└─┘
2220  
2221  theorem reverse_prefix {l₁ l₂ : list α} : reverse l₁ <+: reverse l₂ ↔ l₁ <:+ l₂ :=
id                                   └──┘     └─────┘ └┘ └─┘ └─────┘ └┘  └┘ └─┘ └┘
src                                  └──┘      └─────┘    └─┘ └─────┘        └─┘
typ                                  └──┘     └─────┘ └┘ └─┘ └─────┘ └┘  └┘ └─┘ └┘
doc                                                       └─┘                 └─┘
2222  by rw ← reverse_suffix; simp only [reverse_reverse]
id           └────────────┘             └─────────────┘
src     └───┘└────────────┘  └─────────┘└─────────────┘└─
typ     └───┘└────────────┘  └─────────┘└─────────────┘└─
doc     └───┘                └─────────┘               └─
txt     └───┘                └─────────┘               └─
par     └───┘                └─────────┘               └─
pid       └─┘                    └──┘└┘               
st     └─────────────────────────────────────────────────
2223  
src  
typ  
doc  
txt  
par  
pid  
st   
2224  theorem length_le_of_infix {l₁ l₂ : list α} (s : l₁ <:+: l₂) : length l₁ ≤ length l₂ :=
id                                       └──┘        └┘ └──┘ └┘    └────┘ └┘  └────┘ └┘
src                                      └──┘            └──┘       └────┘     └────┘
typ                                      └──┘        └┘ └──┘ └┘    └────┘ └┘  └────┘ └┘
doc                                                      └──┘
2225  length_le_of_sublist $ sublist_of_infix s
id   └──────────────────┘   └──────────────┘ 
src  └──────────────────┘   └──────────────┘
typ  └──────────────────┘   └──────────────┘ 
2226  
2227  theorem eq_nil_of_infix_nil {l : list α} (s : l <:+: []) : l = [] :=
id                                    └──┘         └──┘ └┘      └┘
src                                   └──┘           └──┘ └┘       └┘
typ                                   └──┘         └──┘ └┘      └┘
doc                                                  └──┘
2228  eq_nil_of_sublist_nil $ sublist_of_infix s
id   └───────────────────┘   └──────────────┘ 
src  └───────────────────┘   └──────────────┘
typ  └───────────────────┘   └──────────────┘ 
2229  
2230  theorem eq_nil_of_prefix_nil {l : list α} (s : l <+: []) : l = [] :=
id                                     └──┘         └─┘ └┘      └┘
src                                    └──┘           └─┘ └┘       └┘
typ                                    └──┘         └─┘ └┘      └┘
doc                                                   └─┘
2231  eq_nil_of_infix_nil $ infix_of_prefix s
id   └─────────────────┘   └─────────────┘ 
src  └─────────────────┘   └─────────────┘
typ  └─────────────────┘   └─────────────┘ 
2232  
2233  theorem eq_nil_of_suffix_nil {l : list α} (s : l <:+ []) : l = [] :=
id                                     └──┘         └─┘ └┘      └┘
src                                    └──┘           └─┘ └┘       └┘
typ                                    └──┘         └─┘ └┘      └┘
doc                                                   └─┘
2234  eq_nil_of_infix_nil $ infix_of_suffix s
id   └─────────────────┘   └─────────────┘ 
src  └─────────────────┘   └─────────────┘
typ  └─────────────────┘   └─────────────┘ 
2235  
2236  theorem infix_iff_prefix_suffix (l₁ l₂ : list α) : l₁ <:+: l₂ ↔ ∃ t, l₁ <+: t ∧ t <:+ l₂ :=
id                                            └──┘     └┘ └──┘ └┘    └┘ └─┘    └─┘ └┘
src                                           └──┘         └──┘           └─┘      └─┘
typ                                           └──┘     └┘ └──┘ └┘    └┘ └─┘    └─┘ └┘
doc                                                        └──┘              └─┘       └─┘
2237  ⟨λ⟨s, t, e⟩, ⟨l₁ ++ t, ⟨_, rfl⟩, by rw [← e, append_assoc]; exact ⟨_, rfl⟩⟩,
id               └┘ └┘        └─┘              └──────────┘             └─┘
src                   └┘        └─┘      └────┘ └┘└──────────┘  └────┘ └─┘└─┘
typ              └┘ └┘        └─┘      └────┘└┘└──────────┘  └────┘ └─┘└─┘
doc                                      └────┘ └┘              └────┘ └─┘   
txt                                      └────┘ └┘              └────┘ └─┘   
par                                      └────┘ └┘              └────┘ └─┘   
pid                                        └──┘ └┘                    └─┘   
st                                      └──────┘└────────────┘└──────────────┘
2238  λ⟨._, ⟨t, rfl⟩, ⟨s, e⟩⟩, ⟨s, t, by rw append_assoc; exact e⟩⟩
id           └─┘                        └──────────┘        
src            └─┘                      └─┘└──────────┘  └────┘
typ          └─┘                     └─┘└──────────┘  └────┘
doc                                     └─┘              └────┘
txt                                     └─┘              └────┘
par                                     └─┘              └────┘
pid                                                          
st                                     └───────────────────────┘
2239  
2240  theorem eq_of_infix_of_length_eq {l₁ l₂ : list α} (s : l₁ <:+: l₂) : length l₁ = length l₂ → l₁ = l₂ :=
id                                             └──┘        └┘ └──┘ └┘    └────┘ └┘  └────┘ └┘   └┘  └┘
src                                            └──┘            └──┘       └────┘     └────┘         
typ                                            └──┘        └┘ └──┘ └┘    └────┘ └┘  └────┘ └┘   └┘  └┘
doc                                                            └──┘
2241  eq_of_sublist_of_length_eq $ sublist_of_infix s
id   └────────────────────────┘   └──────────────┘ 
src  └────────────────────────┘   └──────────────┘
typ  └────────────────────────┘   └──────────────┘ 
2242  
2243  theorem eq_of_prefix_of_length_eq {l₁ l₂ : list α} (s : l₁ <+: l₂) : length l₁ = length l₂ → l₁ = l₂ :=
id                                              └──┘        └┘ └─┘ └┘    └────┘ └┘  └────┘ └┘   └┘  └┘
src                                             └──┘            └─┘       └────┘     └────┘         
typ                                             └──┘        └┘ └─┘ └┘    └────┘ └┘  └────┘ └┘   └┘  └┘
doc                                                             └─┘
2244  eq_of_sublist_of_length_eq $ sublist_of_prefix s
id   └────────────────────────┘   └───────────────┘ 
src  └────────────────────────┘   └───────────────┘
typ  └────────────────────────┘   └───────────────┘ 
2245  
2246  theorem eq_of_suffix_of_length_eq {l₁ l₂ : list α} (s : l₁ <:+ l₂) : length l₁ = length l₂ → l₁ = l₂ :=
id                                              └──┘        └┘ └─┘ └┘    └────┘ └┘  └────┘ └┘   └┘  └┘
src                                             └──┘            └─┘       └────┘     └────┘         
typ                                             └──┘        └┘ └─┘ └┘    └────┘ └┘  └────┘ └┘   └┘  └┘
doc                                                             └─┘
2247  eq_of_sublist_of_length_eq $ sublist_of_suffix s
id   └────────────────────────┘   └───────────────┘ 
src  └────────────────────────┘   └───────────────┘
typ  └────────────────────────┘   └───────────────┘ 
2248  
2249  theorem prefix_of_prefix_length_le : ∀ {l₁ l₂ l₃ : list α},
id                                                     └──┘ 
src                                                     └──┘
typ                                                    └──┘ 
2250   l₁ <+: l₃ → l₂ <+: l₃ → length l₁ ≤ length l₂ → l₁ <+: l₂
id    └┘ └─┘ └┘   └┘ └─┘ └┘   └────┘ └┘  └────┘ └┘   └┘ └─┘ └┘
src      └─┘         └─┘      └────┘     └────┘         └─┘
typ   └┘ └─┘ └┘   └┘ └─┘ └┘   └────┘ └┘  └────┘ └┘   └┘ └─┘ └┘
doc      └─┘         └─┘                                 └─┘
2251  | []      l₂ l₃ h₁ h₂ _ := nil_prefix _
id     └┘                       └────────┘
src    └┘                       └────────┘
typ    └┘                       └────────┘
2252  | (a::l₁) (b::l₂) _ ⟨r₁, rfl⟩ ⟨r₂, e⟩ ll := begin
id       └┘      └┘           └─┘
src      └┘      └┘           └─┘
typ      └┘      └┘           └─┘
st                                               └─────
2253    injection e with _ e', subst b,
id                                 
src    └────────┘ └────────┘  └────┘
typ    └────────┘└────────┘  └────┘
doc    └────────┘ └────────┘  └────┘
txt    └────────┘ └────────┘  └────┘
par    └────────┘ └────────┘  └────┘
pid              └────────┘       
st   ──────────────────────┘└───────┘└─
2254    rcases prefix_of_prefix_length_le ⟨_, rfl⟩ ⟨_, e'⟩
id            └────────────────────────┘     └─┘      └┘
src    └─────┘                           └─┘└─┘└┘ └─┘  └─
typ    └─────┘└────────────────────────┘ └─┘└─┘└┘ └─┘└┘└─
doc    └─────┘                           └─┘   └┘ └─┘  └─
txt    └─────┘                           └─┘   └┘ └─┘  └─
par    └─────┘                           └─┘   └┘ └─┘  └─
pid                                     └─┘   └┘ └─┘  └─
st   ─────────────────────────────────────────────────────
2255      (le_of_succ_le_succ ll) with ⟨r₃, rfl⟩,
id        └────────────────┘ └┘
src  ───┘ └────────────────┘  └──────────────┘
typ  ───┘ └────────────────┘└┘└──────────────┘
doc  ───┘                     └──────────────┘
txt  ───┘                     └──────────────┘
par  ───┘                     └──────────────┘
pid  ───┘                     └──────────────┘
st   ─────────────────────────────────────────┘└─
2256    exact ⟨r₃, rfl⟩
id            └┘  └─┘
src    └────┘   └┘└─┘└┘
typ    └────┘ └┘└┘└─┘└┘
doc    └────┘   └┘   └┘
txt    └────┘   └┘   └┘
par    └────┘   └┘   └┘
pid            └┘   
st   ─────────────────┘
2257  end
st   └─┘
2258  
2259  theorem prefix_or_prefix_of_prefix {l₁ l₂ l₃ : list α}
id                                                  └──┘ 
src                                                 └──┘
typ                                                 └──┘ 
2260   (h₁ : l₁ <+: l₃) (h₂ : l₂ <+: l₃) : l₁ <+: l₂ ∨ l₂ <+: l₁ :=
id          └┘ └─┘ └┘        └┘ └─┘ └┘    └┘ └─┘ └┘  └┘ └─┘ └┘
src            └─┘              └─┘          └─┘        └─┘
typ         └┘ └─┘ └┘        └┘ └─┘ └┘    └┘ └─┘ └┘  └┘ └─┘ └┘
doc            └─┘              └─┘          └─┘         └─┘
2261  (le_total (length l₁) (length l₂)).imp
id    └──────┘  └────┘ └┘   └────┘ └┘  └─┘
src   └──────┘  └────┘      └────┘     └─┘
typ   └──────┘  └────┘ └┘   └────┘ └┘  └─┘
2262    (prefix_of_prefix_length_le h₁ h₂)
id      └────────────────────────┘ └┘ └┘
src     └────────────────────────┘
typ     └────────────────────────┘ └┘ └┘
2263    (prefix_of_prefix_length_le h₂ h₁)
id      └────────────────────────┘ └┘ └┘
src     └────────────────────────┘
typ     └────────────────────────┘ └┘ └┘
2264  
2265  theorem suffix_of_suffix_length_le {l₁ l₂ l₃ : list α}
id                                                  └──┘ 
src                                                 └──┘
typ                                                 └──┘ 
2266   (h₁ : l₁ <:+ l₃) (h₂ : l₂ <:+ l₃) (ll : length l₁ ≤ length l₂) : l₁ <:+ l₂ :=
id          └┘ └─┘ └┘        └┘ └─┘ └┘        └────┘ └┘  └────┘ └┘    └┘ └─┘ └┘
src            └─┘              └─┘           └────┘     └────┘          └─┘
typ         └┘ └─┘ └┘        └┘ └─┘ └┘        └────┘ └┘  └────┘ └┘    └┘ └─┘ └┘
doc            └─┘              └─┘                                       └─┘
2267  reverse_prefix.1 $ prefix_of_prefix_length_le
id   └────────────┘    └────────────────────────┘
src  └────────────┘    └────────────────────────┘
typ  └────────────┘    └────────────────────────┘
2268    (reverse_prefix.2 h₁) (reverse_prefix.2 h₂) (by simp [ll])
id      └────────────┘  └┘   └────────────┘  └┘            └┘
src     └────────────┘       └────────────┘          └────┘  
typ     └────────────┘  └┘   └────────────┘  └┘      └────┘└┘
doc                                                    └────┘  
txt                                                    └────┘  
par                                                    └────┘  
pid                                                          
st                                                    └────────┘
2269  
2270  theorem suffix_or_suffix_of_suffix {l₁ l₂ l₃ : list α}
id                                                  └──┘ 
src                                                 └──┘
typ                                                 └──┘ 
2271   (h₁ : l₁ <:+ l₃) (h₂ : l₂ <:+ l₃) : l₁ <:+ l₂ ∨ l₂ <:+ l₁ :=
id          └┘ └─┘ └┘        └┘ └─┘ └┘    └┘ └─┘ └┘  └┘ └─┘ └┘
src            └─┘              └─┘          └─┘        └─┘
typ         └┘ └─┘ └┘        └┘ └─┘ └┘    └┘ └─┘ └┘  └┘ └─┘ └┘
doc            └─┘              └─┘          └─┘         └─┘
2272  (prefix_or_prefix_of_prefix (reverse_prefix.2 h₁) (reverse_prefix.2 h₂)).imp
id    └────────────────────────┘  └────────────┘  └┘   └────────────┘  └┘  └─┘
src   └────────────────────────┘  └────────────┘       └────────────┘      └─┘
typ   └────────────────────────┘  └────────────┘  └┘   └────────────┘  └┘  └─┘
2273    reverse_prefix.1 reverse_prefix.1
id     └────────────┘  └────────────┘
src    └────────────┘  └────────────┘
typ    └────────────┘  └────────────┘
2274  
2275  theorem infix_of_mem_join : ∀ {L : list (list α)} {l}, l ∈ L → l <:+: join L
id                                     └──┘  └──┘              └──┘ └──┘ 
src                                     └──┘  └──┘                   └──┘ └──┘
typ                                    └──┘  └──┘              └──┘ └──┘ 
doc                                                                   └──┘
2276  | (_  :: L) l (or.inl rfl) := infix_append [] _ _
id         └┘       └────┘ └─┘     └──────────┘ └┘
src        └┘       └────┘ └─┘     └──────────┘ └┘
typ        └┘       └────┘ └─┘     └──────────┘ └┘
2277  | (l' :: L) l (or.inr h)   :=
id         └┘       └────┘ 
src        └┘       └────┘
typ        └┘       └────┘ 
2278    is_infix.trans (infix_of_mem_join h) $ infix_of_suffix $ suffix_append _ _
id     └────────────┘  └───────────────┘      └─────────────┘   └───────────┘
src    └────────────┘                         └─────────────┘   └───────────┘
typ    └────────────┘  └───────────────┘      └─────────────┘   └───────────┘
2279  
2280  theorem prefix_append_left_inj {l₁ l₂ : list α} (l) : l ++ l₁ <+: l ++ l₂ ↔ l₁ <+: l₂ :=
id                                           └──┘          └┘ └┘ └─┘  └┘ └┘  └┘ └─┘ └┘
src                                          └──┘            └┘    └─┘   └┘        └─┘
typ                                          └──┘          └┘ └┘ └─┘  └┘ └┘  └┘ └─┘ └┘
doc                                                                └─┘              └─┘
2281  exists_congr $ λ r, by rw [append_assoc, append_left_inj]
id   └──────────┘              └──────────┘  └─────────────┘
src  └──────────┘           └──┘└──────────┘└┘└─────────────┘└─
typ  └──────────┘          └──┘└──────────┘└┘└─────────────┘└─
doc                         └──┘            └┘               └─
txt                         └──┘            └┘               └─
par                         └──┘            └┘               └─
pid                           └┘            └┘               
st                         └───────────────┘└───────────────┘
2282  
src  
typ  
doc  
txt  
par  
pid  
st   
2283  theorem prefix_cons_inj {l₁ l₂ : list α} (a) : a :: l₁ <+: a :: l₂ ↔ l₁ <+: l₂ :=
id                                    └──┘          └┘ └┘ └─┘  └┘ └┘  └┘ └─┘ └┘
src                                   └──┘            └┘    └─┘   └┘        └─┘
typ                                   └──┘          └┘ └┘ └─┘  └┘ └┘  └┘ └─┘ └┘
doc                                                         └─┘              └─┘
2284  prefix_append_left_inj [a]
id   └────────────────────┘ 
src  └────────────────────┘  
typ  └────────────────────┘ 
2285  
2286  theorem take_prefix (n) (l : list α) : take n l <+: l := ⟨_, take_append_drop _ _⟩
id                                └──┘     └──┘   └─┘         └──────────────┘
src                               └──┘      └──┘     └─┘          └──────────────┘
typ                               └──┘     └──┘   └─┘         └──────────────┘
doc                                                  └─┘
2287  
2288  theorem drop_suffix (n) (l : list α) : drop n l <:+ l := ⟨_, take_append_drop _ _⟩
id                                └──┘     └──┘   └─┘         └──────────────┘
src                               └──┘      └──┘     └─┘          └──────────────┘
typ                               └──┘     └──┘   └─┘         └──────────────┘
doc                                                  └─┘
2289  
2290  theorem prefix_iff_eq_append {l₁ l₂ : list α} : l₁ <+: l₂ ↔ l₁ ++ drop (length l₁) l₂ = l₂ :=
id                                         └──┘     └┘ └─┘ └┘  └┘ └┘ └──┘  └────┘ └┘  └┘  └┘
src                                        └──┘         └─┘        └┘ └──┘  └────┘        
typ                                        └──┘     └┘ └─┘ └┘  └┘ └┘ └──┘  └────┘ └┘  └┘  └┘
doc                                                     └─┘
2291  ⟨by rintros ⟨r, rfl⟩; rw drop_left, λ e, ⟨_, e⟩⟩
id                            └───────┘          
src      └──────────────┘  └─┘└───────┘
typ      └──────────────┘  └─┘└───────┘          
doc      └──────────────┘  └─┘
txt      └──────────────┘  └─┘
par      └──────────────┘  └─┘
pid             └───────┘    
st      └────────────────────┘└───────┘
2292  
2293  theorem suffix_iff_eq_append {l₁ l₂ : list α} : l₁ <:+ l₂ ↔ take (length l₂ - length l₁) l₂ ++ l₁ = l₂ :=
id                                         └──┘     └┘ └─┘ └┘  └──┘  └────┘ └┘  └────┘ └┘  └┘ └┘ └┘  └┘
src                                        └──┘         └─┘     └──┘  └────┘     └────┘        └┘    
typ                                        └──┘     └┘ └─┘ └┘  └──┘  └────┘ └┘  └────┘ └┘  └┘ └┘ └┘  └┘
doc                                                     └─┘
2294  ⟨by rintros ⟨r, rfl⟩; simp only [length_append, nat.add_sub_cancel, take_left], λ e, ⟨_, e⟩⟩
id                                    └───────────┘  └────────────────┘  └───────┘           
src      └──────────────┘  └─────────┘└───────────┘└┘└────────────────┘└┘└───────┘
typ      └──────────────┘  └─────────┘└───────────┘└┘└────────────────┘└┘└───────┘          
doc      └──────────────┘  └─────────┘             └┘                  └┘         
txt      └──────────────┘  └─────────┘             └┘                  └┘         
par      └──────────────┘  └─────────┘             └┘                  └┘         
pid             └───────┘      └──┘└┘             └┘                  └┘         
st      └─────────────────────────────────────────────────────────────────────────┘
2295  
2296  theorem prefix_iff_eq_take {l₁ l₂ : list α} : l₁ <+: l₂ ↔ l₁ = take (length l₁) l₂ :=
id                                       └──┘     └┘ └─┘ └┘  └┘  └──┘  └────┘ └┘  └┘
src                                      └──┘         └─┘         └──┘  └────┘
typ                                      └──┘     └┘ └─┘ └┘  └┘  └──┘  └────┘ └┘  └┘
doc                                                   └─┘
2297  ⟨λ h, append_right_cancel $
id        └─────────────────┘
src        └─────────────────┘
typ       └─────────────────┘
2298    (prefix_iff_eq_append.1 h).trans (take_append_drop _ _).symm,
id      └──────────────────┘   └───┘   └──────────────┘     └──┘
src     └──────────────────┘    └───┘   └──────────────┘     └──┘
typ     └──────────────────┘   └───┘   └──────────────┘     └──┘
2299   λ e, e.symm ▸ take_prefix _ _⟩
id        └───┘  └─────────┘
src         └───┘  └─────────┘
typ       └───┘  └─────────┘
2300  
2301  theorem suffix_iff_eq_drop {l₁ l₂ : list α} : l₁ <:+ l₂ ↔ l₁ = drop (length l₂ - length l₁) l₂ :=
id                                       └──┘     └┘ └─┘ └┘  └┘  └──┘  └────┘ └┘  └────┘ └┘  └┘
src                                      └──┘         └─┘         └──┘  └────┘     └────┘
typ                                      └──┘     └┘ └─┘ └┘  └┘  └──┘  └────┘ └┘  └────┘ └┘  └┘
doc                                                   └─┘
2302  ⟨λ h, append_left_cancel $
id        └────────────────┘
src        └────────────────┘
typ       └────────────────┘
2303    (suffix_iff_eq_append.1 h).trans (take_append_drop _ _).symm,
id      └──────────────────┘   └───┘   └──────────────┘     └──┘
src     └──────────────────┘    └───┘   └──────────────┘     └──┘
typ     └──────────────────┘   └───┘   └──────────────┘     └──┘
2304   λ e, e.symm ▸ drop_suffix _ _⟩
id        └───┘  └─────────┘
src         └───┘  └─────────┘
typ       └───┘  └─────────┘
2305  
2306  instance decidable_prefix [decidable_eq α] : ∀ (l₁ l₂ : list α), decidable (l₁ <+: l₂)
id                              └──────────┘               └──┘    └───────┘  └┘ └─┘ └┘
src                             └──────────┘                 └──┘     └───────┘     └─┘
typ                             └──────────┘               └──┘    └───────┘  └┘ └─┘ └┘
doc                                                                                 └─┘
2307  | []      l₂ := is_true ⟨l₂, rfl⟩
id     └┘      └┘    └─────┘      └─┘
src    └┘            └─────┘      └─┘
typ    └┘      └┘    └─────┘      └─┘
2308  | (a::l₁) [] := is_false $ λ ⟨t, te⟩, list.no_confusion te
id       └┘    └┘    └──────┘        └┘   └───────────────┘
src      └┘    └┘    └──────┘              └───────────────┘
typ      └┘    └┘    └──────┘        └┘   └───────────────┘
2309  | (a::l₁) (b::l₂) :=
id      └┘└┘   └┘└┘
src      └┘      └┘
typ     └┘└┘   └┘└┘
2310    if h : a = b then
id     └┘       
src    └┘       
typ    └┘       
2311      @decidable_of_iff _ _ (by rw [← h, prefix_cons_inj])
id        └──────────────┘                 └─────────────┘
src       └──────────────┘         └────┘ └┘└─────────────┘
typ       └──────────────┘         └────┘└┘└─────────────┘
doc                                └────┘ └┘               
txt                                └────┘ └┘               
par                                └────┘ └┘               
pid                                  └──┘ └┘               
st                                └──────┘└───────────────┘
2312        (decidable_prefix l₁ l₂)
id          └──────────────┘
typ         └──────────────┘
2313    else
2314      is_false $ λ ⟨t, te⟩, h $ by injection te
id       └──────┘                            └┘
src      └──────┘                     └────────┘  
typ      └──────┘                  └────────┘└┘
doc                                   └────────┘  
txt                                   └────────┘  
par                                   └────────┘  
pid                                              
st                                   └─────────────
2315  
src  
typ  
doc  
txt  
par  
pid  
st   
2316  -- Alternatively, use mem_tails
src  ───────────────────────────────┘
typ  ───────────────────────────────┘
doc  ───────────────────────────────┘
txt  ───────────────────────────────┘
par  ───────────────────────────────┘
pid  ───────────────────────────────┘
st   ───────────────────────────────┘
2317  instance decidable_suffix [decidable_eq α] : ∀ (l₁ l₂ : list α), decidable (l₁ <:+ l₂)
id                              └──────────┘               └──┘    └───────┘  └┘ └─┘ └┘
src                             └──────────┘                 └──┘     └───────┘     └─┘
typ                             └──────────┘               └──┘    └───────┘  └┘ └─┘ └┘
doc                                                                                 └─┘
2318  | []      l₂ := is_true ⟨l₂, append_nil _⟩
id     └┘      └┘    └─────┘      └────────┘
src    └┘            └─────┘      └────────┘
typ    └┘      └┘    └─────┘      └────────┘
2319  | (a::l₁) [] := is_false $ mt (length_le_of_sublist ∘ sublist_of_suffix) dec_trivial
id       └┘    └┘    └──────┘   └┘  └──────────────────┘  └───────────────┘  └─────────┘
src      └┘    └┘    └──────┘   └┘  └──────────────────┘  └───────────────┘  └─────────┘
typ      └┘    └┘    └──────┘   └┘  └──────────────────┘  └───────────────┘  └─────────┘
doc                                                                           └─────────┘
2320  | l₁      l₂ := let len1 := length l₁, len2 := length l₂ in
id     └┘      └┘        └──┘    └────┘     └──┘    └────┘
src                              └────┘             └────┘
typ    └┘      └┘        └──┘    └────┘     └──┘    └────┘
2321    if hl : len1 ≤ len2 then
id     └┘      └──┘  └──┘
src    └┘           
typ    └┘      └──┘  └──┘
2322      decidable_of_iff' (l₁ = drop (len2-len1) l₂) suffix_iff_eq_drop
id       └───────────────┘      └──┘  └──┘└──┘      └────────────────┘
src      └───────────────┘      └──┘                └────────────────┘
typ      └───────────────┘      └──┘  └──┘└──┘      └────────────────┘
2323    else is_false $ λ h, hl $ length_le_of_sublist $ sublist_of_suffix h
id          └──────┘      └┘   └──────────────────┘   └───────────────┘ 
src         └──────┘             └──────────────────┘   └───────────────┘
typ         └──────┘      └┘   └──────────────────┘   └───────────────┘ 
2324  
2325  @[simp] theorem mem_inits : ∀ (s t : list α), s ∈ inits t ↔ s <+: t
id                                       └──┘      └───┘    └─┘ 
src                                       └──┘        └───┘      └─┘
typ                                      └──┘      └───┘    └─┘ 
doc    └──┘                                            └───┘       └─┘
2326  | s []     := suffices s = nil ↔ s <+: nil, by simpa only [inits, mem_singleton],
id      └┘                    └─┘    └─┘ └─┘                 └───┘  └───────────┘
src      └┘                    └─┘    └─┘ └─┘     └──────────┘└───┘└┘└───────────┘
typ     └┘                    └─┘    └─┘ └─┘     └──────────┘└───┘└┘└───────────┘
doc                                     └─┘         └──────────┘└───┘└┘             
txt                                                 └──────────┘     └┘             
par                                                 └──────────┘     └┘             
pid                                                      └──┘└┘     └┘             
st                                                 └────────────────────────────────┘
2327    ⟨λh, h.symm ▸ prefix_refl [], eq_nil_of_prefix_nil⟩
id         └───┘  └─────────┘ └┘  └──────────────────┘
src          └───┘  └─────────┘ └┘  └──────────────────┘
typ        └───┘  └─────────┘ └┘  └──────────────────┘
2328  | s (a::t) :=
id       └┘
src        └┘
typ      └┘
2329    suffices (s = nil ∨ ∃ l ∈ inits t, a :: l = s) ↔ s <+: a :: t, by simpa,
id                  └─┘      └───┘     └┘         └─┘   └┘
src                 └─┘       └───┘     └┘          └─┘   └┘       └───┘
typ                 └─┘      └───┘     └┘         └─┘   └┘       └───┘
doc                              └───┘                    └─┘            └───┘
txt                                                                      └───┘
par                                                                      └───┘
st                                                                      └────┘
2330    ⟨λo, match s, o with
id                  
typ                 
2331    | ._, or.inl rfl := ⟨_, rfl⟩
id           └────┘ └─┘        └─┘
src          └────┘ └─┘        └─┘
typ          └────┘ └─┘        └─┘
2332    | s, or.inr ⟨r, hr, hs⟩ := let ⟨s, ht⟩ := (mem_inits _ _).1 hr in
id          └────┘     └┘         └─┘             └───────┘     
src         └────┘                                              
typ         └────┘     └┘         └─┘             └───────┘     
2333      by rw [← hs, ← ht]; exact ⟨s, rfl⟩
id                └┘    └┘            └─┘
src         └────┘  └──┘    └────┘  └┘└─┘└─
typ         └────┘└┘└──┘└┘  └────┘ └┘└─┘└─
doc         └────┘  └──┘    └────┘  └┘   └─
txt         └────┘  └──┘    └────┘  └┘   └─
par         └────┘  └──┘    └────┘  └┘   └─
pid           └──┘  └──┘           └┘   
st         └───────┘└────┘└────────────────
2334    end, λmi, match s, mi with
id           └┘           └┘
src  ─┘
typ  ─┘      └┘           └┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘
2335    | [], ⟨._, rfl⟩ := or.inl rfl
id       └┘       └─┘     └────┘ └─┘
src      └┘       └─┘     └────┘ └─┘
typ      └┘       └─┘     └────┘ └─┘
2336    | (b::s), ⟨r, hr⟩ := list.no_confusion hr $ λba (st : s++r = t), or.inr $
id         └┘      └┘     └───────────────┘       └┘        └┘       └────┘
src        └┘               └───────────────┘                 └┘       └────┘
typ        └┘      └┘     └───────────────┘       └┘        └┘       └────┘
2337      by rw ba; exact ⟨_, (mem_inits _ _).2 ⟨_, st⟩, rfl⟩
id             └┘             └───────┘            └┘   └─┘
src         └─┘    └────┘ └─┘          └──────┘ └─┘  └─┘└─┘└─
typ         └─┘└┘  └────┘ └─┘ └───────┘└──────┘ └─┘└┘└─┘└─┘└─
doc         └─┘    └────┘ └─┘          └──────┘ └─┘  └─┘   └─
txt         └─┘    └────┘ └─┘          └──────┘ └─┘  └─┘   └─
par         └─┘    └────┘ └─┘          └──────┘ └─┘  └─┘   └─
pid                     └─┘          └──────┘ └─┘  └─┘   
st         └─────────────────────────────────────────────────
2338    end⟩
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘
2339  
2340  @[simp] theorem mem_tails : ∀ (s t : list α), s ∈ tails t ↔ s <:+ t
id                                       └──┘      └───┘    └─┘ 
src                                       └──┘        └───┘      └─┘
typ                                      └──┘      └───┘    └─┘ 
doc    └──┘                                            └───┘       └─┘
2341  | s []     := by simp only [tails, mem_singleton]; exact ⟨λh, by rw h; exact suffix_refl [], eq_nil_of_suffix_nil⟩
id       └┘                      └───┘  └───────────┘                                            └──────────────────┘
src      └┘           └─────────┘└───┘└┘└───────────┘  └────┘  └─┘  └─┘ └──────┘             └┘└──────────────────┘└┘
typ      └┘           └─────────┘└───┘└┘└───────────┘  └────┘  └─┘  └─┘└──────┘             └┘└──────────────────┘└┘
doc                   └─────────┘└───┘└┘               └────┘  └─┘  └─┘ └──────┘             └┘                    └┘
txt                   └─────────┘     └┘               └────┘  └─┘  └─┘ └──────┘             └┘                    └┘
par                   └─────────┘     └┘               └────┘  └─┘  └─┘ └──────┘             └┘                    └┘
pid                       └──┘└┘     └┘                      └─┘  └──┘ └──────┘             └┘                    
st                   └──────────────────────────────────────────────┘└─────────────────────────┘└──────────────────────┘
2342  | s (a::t) := by simp only [tails, mem_cons_iff, mem_tails s t]; exact show s = a :: t ∨ s <:+ t ↔ s <:+ a :: t, from
id         └┘                    └───┘  └──────────┘  └───────┘                              └─┘   
src        └┘         └─────────┘└───┘└┘└──────────┘└┘             └────┘           └─┘          └──────
typ        └┘         └─────────┘└───┘└┘└──────────┘└┘└───────┘  └────┘           └─┘         └──────
doc                   └─────────┘└───┘└┘            └┘             └────┘            └─┘          └──────
txt                   └─────────┘     └┘            └┘             └────┘                         └──────
par                   └─────────┘     └┘            └┘             └────┘                         └──────
pid                       └──┘└┘     └┘            └┘                                           └──────
st                   └─────────────────────────────────────────────────────────────────────────────────────────────────────
2343    ⟨λo, match s, t, o with
src  ─┘  └─┘      └┘ └┘ └─────
typ  ─┘  └─┘      └┘ └┘ └─────
doc  ─┘  └─┘      └┘ └┘ └─────
txt  ─┘  └─┘      └┘ └┘ └─────
par  ─┘  └─┘      └┘ └┘ └─────
pid  ─┘  └─┘      └┘ └┘ └─────
st   ──────────────────────────
2344    | ._, t, or.inl rfl := suffix_refl _
id                            └─────────┘
src  ───┘  └┘ └┘         └──┘└─────────┘└──
typ  ───┘  └┘ └┘         └──┘└─────────┘└──
doc  ───┘  └┘ └┘         └──┘           └──
txt  ───┘  └┘ └┘         └──┘           └──
par  ───┘  └┘ └┘         └──┘           └──
pid  ───┘  └┘ └┘         └──┘           └──
st   ───────────────────────────────────────
2345    | s, ._, or.inr ⟨l, rfl⟩ := ⟨a::l, rfl⟩
id                                 
src  ───┘ └┘  └┘        └┘   └───┘     └┘   └─
typ  ───┘ └┘  └┘       └┘   └───┘    └┘   └─
doc  ───┘ └┘  └┘        └┘   └───┘     └┘   └─
txt  ───┘ └┘  └┘        └┘   └───┘     └┘   └─
par  ───┘ └┘  └┘        └┘   └───┘     └┘   └─
pid  ───┘ └┘  └┘        └┘   └───┘     └┘   └─
st   ──────────────────────────────────────────
2346    end, λe, match s, t, e with
id                      
src  ──────┘ └─┘      └┘ └┘ └─────
typ  ──────┘ └─┘     └┘└┘ └─────
doc  ──────┘ └─┘      └┘ └┘ └─────
txt  ──────┘ └─┘      └┘ └┘ └─────
par  ──────┘ └─┘      └┘ └┘ └─────
pid  ──────┘ └─┘      └┘ └┘ └─────
st   ──────────────────────────────
2347    | ._, t, ⟨[], rfl⟩ := or.inl rfl
id                           └────┘ └─┘
src  ───┘  └┘ └┘   └┘   └───┘└────┘└─┘
typ  ───┘  └┘ └┘   └┘   └───┘└────┘└─┘
doc  ───┘  └┘ └┘   └┘   └───┘         
txt  ───┘  └┘ └┘   └┘   └───┘         
par  ───┘  └┘ └┘   └┘   └───┘         
pid  ───┘  └┘ └┘   └┘   └───┘         
st   ───────────────────────────────────
2348    | s, t, ⟨b::l, he⟩ := list.no_confusion he (λab lt, or.inr ⟨l, lt⟩)
id                   └┘     └───────────────┘             └────┘
src  ───┘ └┘ └┘     └┘  └───┘└───────────────┘    └─────┘└────┘  └┘  └──
typ  ───┘ └┘ └┘    └┘└┘└───┘└───────────────┘    └─────┘└────┘  └┘  └──
doc  ───┘ └┘ └┘     └┘  └───┘                     └─────┘        └┘  └──
txt  ───┘ └┘ └┘     └┘  └───┘                     └─────┘        └┘  └──
par  ───┘ └┘ └┘     └┘  └───┘                     └─────┘        └┘  └──
pid  ───┘ └┘ └┘     └┘  └───┘                     └─────┘        └┘  └──
st   ──────────────────────────────────────────────────────────────────────
2349    end⟩
src  ───────
typ  ───────
doc  ───────
txt  ───────
par  ───────
pid  ─────┘
st   ───────
2350  
src  
typ  
doc  
txt  
par  
pid  
st   
2351  instance decidable_infix [decidable_eq α] : ∀ (l₁ l₂ : list α), decidable (l₁ <:+: l₂)
id                             └──────────┘               └──┘    └───────┘  └┘ └──┘ └┘
src                            └──────────┘                 └──┘     └───────┘     └──┘
typ                            └──────────┘               └──┘    └───────┘  └┘ └──┘ └┘
doc                                                                                └──┘
2352  | []      l₂ := is_true ⟨[], l₂, rfl⟩
id     └┘      └┘    └─────┘  └┘      └─┘
src    └┘            └─────┘  └┘      └─┘
typ    └┘      └┘    └─────┘  └┘      └─┘
2353  | (a::l₁) [] := is_false $ λ⟨s, t, te⟩, absurd te $ append_ne_nil_of_ne_nil_left _ _ $
id       └┘    └┘    └──────┘          └┘   └────┘      └──────────────────────────┘
src      └┘    └┘    └──────┘                └────┘      └──────────────────────────┘
typ      └┘    └┘    └──────┘          └┘   └────┘      └──────────────────────────┘
2354                  append_ne_nil_of_ne_nil_right _ _ $ λh, list.no_confusion h
id                   └───────────────────────────┘          └───────────────┘ 
src                  └───────────────────────────┘           └───────────────┘
typ                  └───────────────────────────┘          └───────────────┘ 
2355  | l₁      l₂ := decidable_of_decidable_of_iff (list.decidable_bex (λt, l₁ <+: t) (tails l₂)) $
id     └┘      └┘    └───────────────────────────┘  └────────────────┘        └─┘    └───┘
src                  └───────────────────────────┘  └────────────────┘         └─┘     └───┘
typ    └┘      └┘    └───────────────────────────┘  └────────────────┘        └─┘    └───┘
doc                                                                            └─┘     └───┘
2356    by refine (exists_congr (λt, _)).trans (infix_iff_prefix_suffix _ _).symm;
id                └──────────┘                 └─────────────────────┘
src       └─────┘ └──────────┘  └───────────┘ └─────────────────────┘└────────┘
typ       └─────┘ └──────────┘  └───────────┘ └─────────────────────┘└────────┘
doc       └─────┘               └───────────┘                        └────────┘
txt       └─────┘               └───────────┘                        └────────┘
par       └─────┘               └───────────┘                        └────────┘
pid                            └───────────┘                        └───────┘
st       └────────────────────────────────────────────────────────────────────────
2357       exact ⟨λ⟨h1, h2⟩, ⟨h2, (mem_tails _ _).1 h1⟩, λ⟨h2, h1⟩, ⟨(mem_tails _ _).2 h1, h2⟩⟩
id                 └┘  └┘                                 └┘  └┘     └───────┘
src       └────┘    └┘  └─┘   └┘          └──────┘  └─┘   └┘  └─┘  └───────┘└──────┘  └┘  └──
typ       └────┘  └┘└┘└┘└─┘   └┘          └──────┘  └─┘ └┘└┘└┘└─┘  └───────┘└──────┘  └┘  └──
doc       └────┘    └┘  └─┘   └┘          └──────┘  └─┘   └┘  └─┘           └──────┘  └┘  └──
txt       └────┘    └┘  └─┘   └┘          └──────┘  └─┘   └┘  └─┘           └──────┘  └┘  └──
par       └────┘    └┘  └─┘   └┘          └──────┘  └─┘   └┘  └─┘           └──────┘  └┘  └──
pid                └┘  └─┘   └┘          └──────┘  └─┘   └┘  └─┘           └──────┘  └┘  └┘
st   ──────────────────────────────────────────────────────────────────────────────────────────
2358  
src  
typ  
doc  
txt  
par  
pid  
st   
2359  /- sublists -/
src  ───────────────
typ  ───────────────
doc  ───────────────
txt  ───────────────
par  ───────────────
pid  ───────────────
st   ───────────────
2360  
src  
typ  
doc  
txt  
par  
pid  
st   
2361  @[simp] theorem sublists'_nil : sublists' (@nil α) = [[]] := rfl
id                                   └───────┘   └─┘    └┘    └─┘
src                                  └───────┘   └─┘     └──┘    └─┘
typ                                  └───────┘   └─┘    └┘    └─┘
doc    └──┘                          └───────┘
2362  
2363  @[simp] theorem sublists'_singleton (a : α) : sublists' [a] = [[], [a]] := rfl
id                                                └───────┘   └┘ └┘    └─┘
src                                                └───────┘    └──┘  └┘    └─┘
typ                                               └───────┘   └┘ └┘    └─┘
doc    └──┘                                        └───────┘
2364  
2365  theorem map_sublists'_aux (g : list β → list γ) (l : list α) (f r) :
id                                  └──┘    └──┘        └──┘ 
src                                 └──┘     └──┘         └──┘
typ                                 └──┘    └──┘        └──┘ 
2366    map g (sublists'_aux l f r) = sublists'_aux l (g ∘ f) (map g r) :=
id     └─┘   └───────────┘      └───────────┘        └─┘  
src    └─┘    └───────────┘         └───────────┘           └─┘
typ    └─┘   └───────────┘      └───────────┘        └─┘  
2367  by induction l generalizing f r; [refl, simp only [*, sublists'_aux]]
id                                                       └───────────┘
src     └────────┘ └───────────────┘  └──┘  └────────────┘└───────────┘
typ     └────────┘└───────────────┘  └──┘  └────────────┘└───────────┘
doc     └────────┘ └───────────────┘   └──┘  └────────────┘             
txt     └────────┘ └───────────────┘   └──┘  └────────────┘             
par     └────────┘ └───────────────┘   └──┘  └────────────┘             
pid               └──────────────┘             └──┘└───┘             
st     └─────────────────────────────────────────────────────────────────┘
2368  
2369  theorem sublists'_aux_append (r' : list (list β)) (l : list α) (f r) :
id                                      └──┘  └──┘         └──┘ 
src                                     └──┘  └──┘          └──┘
typ                                     └──┘  └──┘         └──┘ 
2370    sublists'_aux l f (r ++ r') = sublists'_aux l f r ++ r' :=
id     └───────────┘     └┘ └┘   └───────────┘    └┘ └┘
src    └───────────┘        └┘      └───────────┘       └┘
typ    └───────────┘     └┘ └┘   └───────────┘    └┘ └┘
2371  by induction l generalizing f r; [refl, simp only [*, sublists'_aux]]
id                                                       └───────────┘
src     └────────┘ └───────────────┘  └──┘  └────────────┘└───────────┘
typ     └────────┘└───────────────┘  └──┘  └────────────┘└───────────┘
doc     └────────┘ └───────────────┘   └──┘  └────────────┘             
txt     └────────┘ └───────────────┘   └──┘  └────────────┘             
par     └────────┘ └───────────────┘   └──┘  └────────────┘             
pid               └──────────────┘             └──┘└───┘             
st     └─────────────────────────────────────────────────────────────────┘
2372  
2373  theorem sublists'_aux_eq_sublists' (l f r) :
2374    @sublists'_aux α β l f r = map f (sublists' l) ++ r :=
id      └───────────┘       └─┘   └───────┘   └┘ 
src     └───────────┘            └─┘    └───────┘    └┘
typ     └───────────┘       └─┘   └───────┘   └┘ 
doc                                      └───────┘
2375  by rw [sublists', map_sublists'_aux, ← sublists'_aux_append]; refl
id          └───────┘  └───────────────┘    └──────────────────┘
src     └──┘└───────┘└┘└───────────────┘└──┘└──────────────────┘  └────
typ     └──┘└───────┘└┘└───────────────┘└──┘└──────────────────┘  └────
doc     └──┘└───────┘└┘                 └──┘                      └────
txt     └──┘         └┘                 └──┘                      └────
par     └──┘         └┘                 └──┘                      └────
pid       └┘         └┘                 └──┘                          
st     └────────────┘└─────────────────┘└──────────────────────┘└──────
2376  
src  
typ  
doc  
txt  
par  
pid  
st   
2377  @[simp] theorem sublists'_cons (a : α) (l : list α) :
id                                              └──┘ 
src                                              └──┘
typ                                             └──┘ 
doc    └──┘
2378    sublists' (a :: l) = sublists' l ++ map (cons a) (sublists' l) :=
id     └───────┘   └┘    └───────┘  └┘ └─┘  └──┘    └───────┘ 
src    └───────┘    └┘     └───────┘   └┘ └─┘  └──┘     └───────┘
typ    └───────┘   └┘    └───────┘  └┘ └─┘  └──┘    └───────┘ 
doc    └───────┘            └───────┘                    └───────┘
2379  by rw [sublists', sublists'_aux]; simp only [sublists'_aux_eq_sublists', map_id, append_nil]; refl
id          └───────┘  └───────────┘              └────────────────────────┘  └────┘  └────────┘
src     └──┘└───────┘└┘└───────────┘  └─────────┘└────────────────────────┘└┘└────┘└┘└────────┘  └────
typ     └──┘└───────┘└┘└───────────┘  └─────────┘└────────────────────────┘└┘└────┘└┘└────────┘  └────
doc     └──┘└───────┘└┘               └─────────┘                          └┘      └┘            └────
txt     └──┘         └┘               └─────────┘                          └┘      └┘            └────
par     └──┘         └┘               └─────────┘                          └┘      └┘            └────
pid       └┘         └┘                   └──┘└┘                          └┘      └┘                
st     └────────────┘└─────────────┘└──────────────────────────────────────────────────────────────────
2380  
src  
typ  
doc  
txt  
par  
pid  
st   
2381  @[simp] theorem mem_sublists' {s t : list α} : s ∈ sublists' t ↔ s <+ t :=
id                                        └──┘       └───────┘    └┘ 
src                                       └──┘         └───────┘      └┘
typ                                       └──┘       └───────┘    └┘ 
doc    └──┘                                             └───────┘
2382  begin
st   └─────
2383    induction t with a t IH generalizing s,
id               
src    └────────┘ └─────────────────────────┘
typ    └────────┘└─────────────────────────┘
doc    └────────┘ └─────────────────────────┘
txt    └────────┘ └─────────────────────────┘
par    └────────┘ └─────────────────────────┘
pid              └─────────┘└─────────────┘
st   ───────────────────────────────────────┘└─
2384    { simp only [sublists'_nil, mem_singleton],
id                  └───────────┘  └───────────┘
src      └─────────┘└───────────┘└┘└───────────┘
typ      └─────────┘└───────────┘└┘└───────────┘
doc      └─────────┘             └┘             
txt      └─────────┘             └┘             
par      └─────────┘             └┘             
pid          └──┘└┘             └┘             
st   ───┘└──────────────────────────────────────┘└─
2385      exact ⟨λ h, by rw h, eq_nil_of_sublist_nil⟩ },
id                           └───────────────────┘
src      └────┘  └──┘  └─┘ └┘└───────────────────┘└┘
typ      └────┘  └──┘  └─┘└┘└───────────────────┘└┘
doc      └────┘  └──┘  └─┘ └┘                     └┘
txt      └────┘  └──┘  └─┘ └┘                     └┘
par      └────┘  └──┘  └─┘ └┘                     └┘
pid             └──┘  └──┘ └┘                     
st   ─────────────────┘└───┘└───────────────────────┘└┘
2386    simp only [sublists'_cons, mem_append, IH, mem_map],
id                └────────────┘  └────────┘      └─────┘
src    └─────────┘└────────────┘└┘└────────┘└┘  └┘└─────┘
typ    └─────────┘└────────────┘└┘└────────┘└┘└┘└┘└─────┘
doc    └─────────┘              └┘          └┘  └┘       
txt    └─────────┘              └┘          └┘  └┘       
par    └─────────┘              └┘          └┘  └┘       
pid        └──┘└┘              └┘          └┘  └┘       
st   ────────────────────────────────────────────────────┘└─
2387    split; intro h, rcases h with h | ⟨s, h, rfl⟩,
id                            
src    └───┘  └─────┘  └─────┘ └───────────────────┘
typ    └───┘  └─────┘  └─────┘└───────────────────┘
doc    └───┘  └─────┘  └─────┘ └───────────────────┘
txt    └───┘  └─────┘  └─────┘ └───────────────────┘
par    └───┘  └─────┘  └─────┘ └───────────────────┘
pid                └┘         └───────────────────┘
st   ───────────────┘└─────────────────────────────┘└─
2388    { exact sublist_cons_of_sublist _ h },
id             └─────────────────────┘   
src      └────┘└─────────────────────┘└─┘ 
typ      └────┘└─────────────────────┘└─┘
doc      └────┘                       └─┘ 
txt      └────┘                       └─┘ 
par      └────┘                       └─┘ 
pid                                  └─┘ 
st   ───┘└────────────────────────────────┘└┘
2389    { exact cons_sublist_cons _ h },
id             └───────────────┘   
src      └────┘└───────────────┘└─┘ 
typ      └────┘└───────────────┘└─┘
doc      └────┘                 └─┘ 
txt      └────┘                 └─┘ 
par      └────┘                 └─┘ 
pid                            └─┘ 
st   ───┘└──────────────────────────┘└┘
2390    { cases h with _ _ _ h s _ _ h,
id             
src      └────┘ └───────────────────┘
typ      └────┘└───────────────────┘
doc      └────┘ └───────────────────┘
txt      └────┘ └───────────────────┘
par      └────┘ └───────────────────┘
pid            └───────────────────┘
st   ───────────────────────────────┘└─
2391      { exact or.inl h },
id               └────┘ 
src        └────┘└────┘ 
typ        └────┘└────┘
doc        └────┘       
txt        └────┘       
par        └────┘       
pid                    
st   ─────┘└─────────────┘└┘
2392      { exact or.inr ⟨s, h, rfl⟩ } }
id               └────┘      └─┘
src        └────┘└────┘  └┘ └┘└─┘└┘
typ        └────┘└────┘ └┘└┘└─┘└┘
doc        └────┘        └┘ └┘   └┘
txt        └────┘        └┘ └┘   └┘
par        └────┘        └┘ └┘   └┘
pid                     └┘ └┘   
st   ──────────────────────────────┘└───
2393  end
st   ──┘
2394  
2395  @[simp] theorem length_sublists' : ∀ l : list α, length (sublists' l) = 2 ^ length l
id                                           └──┘   └────┘  └───────┘       └────┘ 
src                                           └──┘    └────┘  └───────┘        └────┘
typ                                          └──┘   └────┘  └───────┘       └────┘ 
doc    └──┘                                                   └───────┘
2396  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
2397  | (a::l) := by simp only [sublists'_cons, length_append, length_sublists' l, length_map,
id       └┘                    └────────────┘  └───────────┘  └──────────────┘   └────────┘
src      └┘         └─────────┘└────────────┘└┘└───────────┘└┘                 └┘└────────┘└─
typ      └┘         └─────────┘└────────────┘└┘└───────────┘└┘└──────────────┘└┘└────────┘└─
doc                 └─────────┘              └┘             └┘                 └┘          └─
txt                 └─────────┘              └┘             └┘                 └┘          └─
par                 └─────────┘              └┘             └┘                 └┘          └─
pid                     └──┘└┘              └┘             └┘                 └┘          └─
st                 └──────────────────────────────────────────────────────────────────────────
2398      length, pow_succ, mul_succ, mul_zero, zero_add]
id       └────┘  └──────┘  └──────┘  └──────┘  └──────┘
src  ───┘└────┘└┘└──────┘└┘└──────┘└┘└──────┘└┘└──────┘└─
typ  ───┘└────┘└┘└──────┘└┘└──────┘└┘└──────┘└┘└──────┘└─
doc  ───┘      └┘        └┘        └┘        └┘        └─
txt  ───┘      └┘        └┘        └┘        └┘        └─
par  ───┘      └┘        └┘        └┘        └┘        └─
pid  ───┘      └┘        └┘        └┘        └┘        
st   ────────────────────────────────────────────────────
2399  
src  
typ  
doc  
txt  
par  
pid  
st   
2400  @[simp] theorem sublists_nil : sublists (@nil α) = [[]] := rfl
id                                  └──────┘   └─┘    └┘    └─┘
src                                 └──────┘   └─┘     └──┘    └─┘
typ                                 └──────┘   └─┘    └┘    └─┘
doc    └──┘                         └──────┘
2401  
2402  @[simp] theorem sublists_singleton (a : α) : sublists [a] = [[], [a]] := rfl
id                                               └──────┘   └┘ └┘    └─┘
src                                               └──────┘    └──┘  └┘    └─┘
typ                                              └──────┘   └┘ └┘    └─┘
doc    └──┘                                       └──────┘
2403  
2404  theorem sublists_aux₁_eq_sublists_aux : ∀ l (f : list α → list β),
id                                                   └──┘   └──┘ 
src                                                   └──┘     └──┘
typ                                                  └──┘   └──┘ 
2405    sublists_aux₁ l f = sublists_aux l (λ ys r, f ys ++ r)
id     └───────────┘    └──────────┘     └┘    └┘ └┘ 
src    └───────────┘      └──────────┘                 └┘
typ    └───────────┘    └──────────┘     └┘    └┘ └┘ 
2406  | []     f := rfl
id     └┘          └─┘
src    └┘          └─┘
typ    └┘          └─┘
2407  | (a::l) f := by rw [sublists_aux₁, sublists_aux]; simp only [*, append_assoc]
id       └┘               └───────────┘  └──────────┘                 └──────────┘
src      └┘           └──┘└───────────┘└┘└──────────┘  └────────────┘└──────────┘└─
typ      └┘           └──┘└───────────┘└┘└──────────┘  └────────────┘└──────────┘└─
doc                   └──┘             └┘              └────────────┘            └─
txt                   └──┘             └┘              └────────────┘            └─
par                   └──┘             └┘              └────────────┘            └─
pid                     └┘             └┘                  └──┘└───┘            
st                   └────────────────┘└────────────┘└─────────────────────────────
2408  
src  
typ  
doc  
txt  
par  
pid  
st   
2409  theorem sublists_aux_cons_eq_sublists_aux₁ (l : list α) :
id                                                   └──┘ 
src                                                  └──┘
typ                                                  └──┘ 
2410    sublists_aux l cons = sublists_aux₁ l (λ x, [x]) :=
id     └──────────┘  └──┘  └───────────┘       
src    └──────────┘   └──┘  └───────────┘          
typ    └──────────┘  └──┘  └───────────┘       
2411  by rw [sublists_aux₁_eq_sublists_aux]; refl
id          └───────────────────────────┘
src     └──┘└───────────────────────────┘  └────
typ     └──┘└───────────────────────────┘  └────
doc     └──┘                               └────
txt     └──┘                               └────
par     └──┘                               └────
pid       └┘                                   
st     └────────────────────────────────┘└──────
2412  
src  
typ  
doc  
txt  
par  
pid  
st   
2413  theorem sublists_aux_eq_foldr.aux {a : α} {l : list α}
id                                                 └──┘ 
src                                                 └──┘
typ                                                └──┘ 
2414    (IH₁ : ∀ (f : list α → list β → list β), sublists_aux l f = foldr f [] (sublists_aux l cons))
id                   └──┘   └──┘    └──┘    └──────────┘    └───┘  └┘  └──────────┘  └──┘
src                  └──┘     └──┘     └──┘     └──────────┘      └───┘   └┘  └──────────┘   └──┘
typ                  └──┘   └──┘    └──┘    └──────────┘    └───┘  └┘  └──────────┘  └──┘
2415    (IH₂ : ∀ (f : list α → list (list α) → list (list α)),
id                   └──┘   └──┘  └──┘     └──┘  └──┘ 
src                  └──┘     └──┘  └──┘      └──┘  └──┘
typ                  └──┘   └──┘  └──┘     └──┘  └──┘ 
2416        sublists_aux l f = foldr f [] (sublists_aux l cons))
id         └──────────┘    └───┘  └┘  └──────────┘  └──┘
src        └──────────┘      └───┘   └┘  └──────────┘   └──┘
typ        └──────────┘    └───┘  └┘  └──────────┘  └──┘
2417    (f : list α → list β → list β) : sublists_aux (a::l) f = foldr f [] (sublists_aux (a::l) cons) :=
id          └──┘    └──┘    └──┘     └──────────┘  └┘    └───┘  └┘  └──────────┘  └┘  └──┘
src         └──┘     └──┘     └──┘      └──────────┘   └┘      └───┘   └┘  └──────────┘   └┘   └──┘
typ         └──┘    └──┘    └──┘     └──────────┘  └┘    └───┘  └┘  └──────────┘  └┘  └──┘
2418  begin
st   └─────
2419    simp only [sublists_aux, foldr_cons], rw [IH₂, IH₁], congr' 1,
id                └──────────┘  └────────┘       └─┘  └─┘
src    └─────────┘└──────────┘└┘└────────┘  └──┘   └┘     └──────┘
typ    └─────────┘└──────────┘└┘└────────┘  └──┘└─┘└┘└─┘  └──────┘
doc    └─────────┘            └┘            └──┘   └┘     └──────┘
txt    └─────────┘            └┘            └──┘   └┘     └──────┘
par    └─────────┘            └┘            └──┘   └┘     └──────┘
pid        └──┘└┘            └┘              └┘   └┘           
st   ─────────────────────────────────────┘└───────┘└───┘└─────────┘└─
2420    induction sublists_aux l cons with _ _ ih, {refl},
id               └──────────┘  └──┘
src    └────────┘└──────────┘ └──┘└──────────┘   └──┘
typ    └────────┘└──────────┘└──┘└──────────┘   └──┘
doc    └────────┘                 └──────────┘   └──┘
txt    └────────┘                 └──────────┘   └──┘
par    └────────┘                 └──────────┘   └──┘
pid                              └─────────┘
st   ──────────────────────────────────────────┘└─────┘└┘
2421    simp only [ih, foldr_cons]
id                └┘  └────────┘
src    └─────────┘  └┘└────────┘└┘
typ    └─────────┘└┘└┘└────────┘└┘
doc    └─────────┘  └┘          └┘
txt    └─────────┘  └┘          └┘
par    └─────────┘  └┘          └┘
pid        └──┘└┘  └┘          
st   ────────────────────────────┘
2422  end
st   └─┘
2423  
2424  theorem sublists_aux_eq_foldr (l : list α) : ∀ (f : list α → list β → list β),
id                                      └──┘            └──┘   └──┘    └──┘ 
src                                     └──┘             └──┘     └──┘     └──┘
typ                                     └──┘            └──┘   └──┘    └──┘ 
2425    sublists_aux l f = foldr f [] (sublists_aux l cons) :=
id     └──────────┘    └───┘  └┘  └──────────┘  └──┘
src    └──────────┘      └───┘   └┘  └──────────┘   └──┘
typ    └──────────┘    └───┘  └┘  └──────────┘  └──┘
2426  suffices _ ∧ ∀ f : list α → list (list α) → list (list α),
id                     └──┘   └──┘  └──┘     └──┘  └──┘ 
src                    └──┘     └──┘  └──┘      └──┘  └──┘
typ                    └──┘   └──┘  └──┘     └──┘  └──┘ 
2427      sublists_aux l f = foldr f [] (sublists_aux l cons),
id       └──────────┘    └───┘  └┘  └──────────┘  └──┘
src      └──────────┘      └───┘   └┘  └──────────┘   └──┘
typ      └──────────┘    └───┘  └┘  └──────────┘  └──┘
2428    from this.1,
id          └──┘
src             
typ         └──┘
2429  begin
st   └─────
2430    induction l with a l IH, {split; intro; refl},
id               
src    └────────┘ └──────────┘   └───┘  └───┘  └──┘
typ    └────────┘└──────────┘   └───┘  └───┘  └──┘
doc    └────────┘ └──────────┘   └───┘  └───┘  └──┘
txt    └────────┘ └──────────┘   └───┘  └───┘  └──┘
par    └────────┘ └──────────┘   └───┘  └───┘  └──┘
pid              └─────────┘
st   ────────────────────────┘└───────────────────┘└┘
2431    exact ⟨sublists_aux_eq_foldr.aux IH.1 IH.2,
src    └────┘                            └─┘  └───
typ    └────┘                            └─┘  └───
doc    └────┘                            └─┘  └───
txt    └────┘                            └─┘  └───
par    └────┘                            └─┘  └───
pid                                     └─┘  └───
st   ──────────────────────────────────────────────
2432           sublists_aux_eq_foldr.aux IH.2 IH.2⟩
id            └───────────────────────┘      └┘
src  ────────┘└───────────────────────┘  └─┘  └──┘
typ  ────────┘└───────────────────────┘  └─┘└┘└──┘
doc  ────────┘                           └─┘  └──┘
txt  ────────┘                           └─┘  └──┘
par  ────────┘                           └─┘  └──┘
pid  ────────┘                           └─┘  └─┘
st   ─────────────────────────────────────────────┘
2433  end
st   └─┘
2434  
2435  theorem sublists_aux_cons_cons (l : list α) (a : α) :
id                                       └──┘        
src                                      └──┘
typ                                      └──┘        
2436    sublists_aux (a::l) cons = [a] :: foldr (λys r, ys :: (a :: ys) :: r) [] (sublists_aux l cons) :=
id     └──────────┘  └┘  └──┘   └┘ └───┘   └┘   └┘ └┘   └┘ └┘  └┘   └┘  └──────────┘  └──┘
src    └──────────┘   └┘   └──┘    └┘ └───┘            └┘    └┘     └┘    └┘  └──────────┘   └──┘
typ    └──────────┘  └┘  └──┘   └┘ └───┘   └┘   └┘ └┘   └┘ └┘  └┘   └┘  └──────────┘  └──┘
2437  by rw [← sublists_aux_eq_foldr]; refl
id            └───────────────────┘
src     └────┘└───────────────────┘  └────
typ     └────┘└───────────────────┘  └────
doc     └────┘                       └────
txt     └────┘                       └────
par     └────┘                       └────
pid       └──┘                           
st     └──────────────────────────┘└──────
2438  
src  
typ  
doc  
txt  
par  
pid  
st   
2439  theorem sublists_aux₁_append : ∀ (l₁ l₂ : list α) (f : list α → list β),
id                                            └──┘        └──┘   └──┘ 
src                                            └──┘         └──┘     └──┘
typ                                           └──┘        └──┘   └──┘ 
2440    sublists_aux₁ (l₁ ++ l₂) f = sublists_aux₁ l₁ f ++
id     └───────────┘  └┘ └┘ └┘    └───────────┘ └┘  └┘
src    └───────────┘     └┘        └───────────┘      └┘
typ    └───────────┘  └┘ └┘ └┘    └───────────┘ └┘  └┘
2441      sublists_aux₁ l₂ (λ x, f x ++ sublists_aux₁ l₁ (f ∘ (++ x)))
id       └───────────┘ └┘        └┘ └───────────┘ └┘       
src      └───────────┘              └┘ └───────────┘        
typ      └───────────┘ └┘        └┘ └───────────┘ └┘       
2442  | []      l₂ f := by simp only [sublists_aux₁, nil_append, append_nil]
id     └┘                            └───────────┘  └────────┘  └────────┘
src    └┘                 └─────────┘└───────────┘└┘└────────┘└┘└────────┘└┘
typ    └┘                 └─────────┘└───────────┘└┘└────────┘└┘└────────┘└┘
doc                       └─────────┘             └┘          └┘          └┘
txt                       └─────────┘             └┘          └┘          └┘
par                       └─────────┘             └┘          └┘          └┘
pid                           └──┘└┘             └┘          └┘          
st                       └─────────────────────────────────────────────────┘
2443  | (a::l₁) l₂ f := by simp only [sublists_aux₁, cons_append, sublists_aux₁_append l₁, append_assoc]; refl
id       └┘                          └───────────┘  └─────────┘  └──────────────────┘ └┘  └──────────┘
src      └┘               └─────────┘└───────────┘└┘└─────────┘└┘                      └┘└──────────┘  └────
typ      └┘               └─────────┘└───────────┘└┘└─────────┘└┘└──────────────────┘└┘└┘└──────────┘  └────
doc                       └─────────┘             └┘           └┘                      └┘              └────
txt                       └─────────┘             └┘           └┘                      └┘              └────
par                       └─────────┘             └┘           └┘                      └┘              └────
pid                           └──┘└┘             └┘           └┘                      └┘                  
st                       └────────────────────────────────────────────────────────────────────────────────────
2444  
src  
typ  
doc  
txt  
par  
pid  
st   
2445  theorem sublists_aux₁_concat (l : list α) (a : α) (f : list α → list β) :
id                                     └──┘               └──┘    └──┘ 
src                                    └──┘                 └──┘     └──┘
typ                                    └──┘               └──┘    └──┘ 
2446    sublists_aux₁ (l ++ [a]) f = sublists_aux₁ l f ++
id     └───────────┘   └┘     └───────────┘   └┘
src    └───────────┘    └┘       └───────────┘     └┘
typ    └───────────┘   └┘     └───────────┘   └┘
2447      f [a] ++ sublists_aux₁ l (λ x, f (x ++ [a])) :=
id         └┘ └───────────┘          └┘ 
src          └┘ └───────────┘              └┘  
typ        └┘ └───────────┘          └┘ 
2448  by simp only [sublists_aux₁_append, sublists_aux₁, append_assoc, append_nil]
id                 └──────────────────┘  └───────────┘  └──────────┘  └────────┘
src     └─────────┘└──────────────────┘└┘└───────────┘└┘└──────────┘└┘└────────┘└─
typ     └─────────┘└──────────────────┘└┘└───────────┘└┘└──────────┘└┘└────────┘└─
doc     └─────────┘                    └┘             └┘            └┘          └─
txt     └─────────┘                    └┘             └┘            └┘          └─
par     └─────────┘                    └┘             └┘            └┘          └─
pid         └──┘└┘                    └┘             └┘            └┘          
st     └──────────────────────────────────────────────────────────────────────────
2449  
src  
typ  
doc  
txt  
par  
pid  
st   
2450  theorem sublists_aux₁_bind : ∀ (l : list α)
id                                      └──┘ 
src                                      └──┘
typ                                     └──┘ 
2451    (f : list α → list β) (g : β → list γ),
id          └──┘   └──┘          └──┘ 
src         └──┘     └──┘             └──┘
typ         └──┘   └──┘          └──┘ 
2452    (sublists_aux₁ l f).bind g = sublists_aux₁ l (λ x, (f x).bind g)
id      └───────────┘   └──┘    └───────────┘          └──┘  
src     └───────────┘     └──┘     └───────────┘              └──┘
typ     └───────────┘   └──┘    └───────────┘          └──┘  
2453  | []     f g := rfl
id     └┘            └─┘
src    └┘            └─┘
typ    └┘            └─┘
2454  | (a::l) f g := by simp only [sublists_aux₁, bind_append, sublists_aux₁_bind l]
id       └┘                        └───────────┘  └─────────┘  └────────────────┘ 
src      └┘             └─────────┘└───────────┘└┘└─────────┘└┘                   └─
typ      └┘             └─────────┘└───────────┘└┘└─────────┘└┘└────────────────┘└─
doc                     └─────────┘             └┘           └┘                   └─
txt                     └─────────┘             └┘           └┘                   └─
par                     └─────────┘             └┘           └┘                   └─
pid                         └──┘└┘             └┘           └┘                   
st                     └─────────────────────────────────────────────────────────────
2455  
src  
typ  
doc  
txt  
par  
pid  
st   
2456  theorem sublists_aux_cons_append (l₁ l₂ : list α) :
id                                             └──┘ 
src                                            └──┘
typ                                            └──┘ 
2457    sublists_aux (l₁ ++ l₂) cons = sublists_aux l₁ cons ++
id     └──────────┘  └┘ └┘ └┘  └──┘  └──────────┘ └┘ └──┘ └┘
src    └──────────┘     └┘     └──┘  └──────────┘    └──┘ └┘
typ    └──────────┘  └┘ └┘ └┘  └──┘  └──────────┘ └┘ └──┘ └┘
2458      (do x ← sublists_aux l₂ cons, (++ x) <$> sublists l₁) :=
id              └──────────┘ └┘ └──┘       └─┘ └──────┘ └┘
src              └──────────┘    └──┘        └─┘ └──────┘
typ             └──────────┘ └┘ └──┘       └─┘ └──────┘ └┘
doc                                               └──────┘
2459  begin
st   └─────
2460    simp only [sublists, sublists_aux_cons_eq_sublists_aux₁, sublists_aux₁_append, bind_eq_bind, sublists_aux₁_bind],
id                └──────┘  └────────────────────────────────┘  └──────────────────┘  └──────────┘  └────────────────┘
src    └─────────┘└──────┘└┘└────────────────────────────────┘└┘└──────────────────┘└┘└──────────┘└┘└────────────────┘
typ    └─────────┘└──────┘└┘└────────────────────────────────┘└┘└──────────────────┘└┘└──────────┘└┘└────────────────┘
doc    └─────────┘└──────┘└┘                                  └┘                    └┘            └┘                  
txt    └─────────┘        └┘                                  └┘                    └┘            └┘                  
par    └─────────┘        └┘                                  └┘                    └┘            └┘                  
pid        └──┘└┘        └┘                                  └┘                    └┘            └┘                  
st   ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘└─
2461    congr, funext x, apply congr_arg _,
id                            └───────┘
src    └───┘  └──────┘  └────┘└───────┘└┘
typ    └───┘  └──────┘  └────┘└───────┘└┘
doc           └──────┘  └────┘         └┘
txt    └───┘  └──────┘  └────┘         └┘
par    └───┘  └──────┘  └────┘         └┘
pid                 └┘                └┘
st   ──────┘└────────┘└─────────────────┘└─
2462    rw [← bind_ret_eq_map, sublists_aux₁_bind], exact (append_nil _).symm
id           └─────────────┘  └────────────────┘          └────────┘
src    └────┘└─────────────┘└┘└────────────────┘  └────┘ └────────┘└───────┘
typ    └────┘└─────────────┘└┘└────────────────┘  └────┘ └────────┘└───────┘
doc    └────┘               └┘                    └────┘           └───────┘
txt    └────┘               └┘                    └────┘           └───────┘
par    └────┘               └┘                    └────┘           └───────┘
pid      └──┘               └┘                                    └─────┘└┘
st   ──────────────────────┘└──────────────────┘└───────────────────────────┘
2463  end
st   └─┘
2464  
2465  theorem sublists_append (l₁ l₂ : list α) :
id                                    └──┘ 
src                                   └──┘
typ                                   └──┘ 
2466    sublists (l₁ ++ l₂) = (do x ← sublists l₂, (++ x) <$> sublists l₁) :=
id     └──────┘  └┘ └┘ └┘          └──────┘ └┘       └─┘ └──────┘ └┘
src    └──────┘     └┘              └──────┘           └─┘ └──────┘
typ    └──────┘  └┘ └┘ └┘          └──────┘ └┘       └─┘ └──────┘ └┘
doc    └──────┘                      └──────┘                └──────┘
2467  by simp only [map, sublists, sublists_aux_cons_append, map_eq_map, bind_eq_bind,
id                 └─┘  └──────┘  └──────────────────────┘  └────────┘  └──────────┘
src     └─────────┘└─┘└┘└──────┘└┘└──────────────────────┘└┘└────────┘└┘└──────────┘└─
typ     └─────────┘└─┘└┘└──────┘└┘└──────────────────────┘└┘└────────┘└┘└──────────┘└─
doc     └─────────┘   └┘└──────┘└┘                        └┘          └┘            └─
txt     └─────────┘   └┘        └┘                        └┘          └┘            └─
par     └─────────┘   └┘        └┘                        └┘          └┘            └─
pid         └──┘└┘   └┘        └┘                        └┘          └┘            └─
st     └──────────────────────────────────────────────────────────────────────────────
2468    cons_bind, map_id', append_nil, cons_append, map_id' (λ _, rfl)]; split; refl
id     └───────┘  └─────┘  └────────┘  └─────────┘  └─────┘       └─┘
src  ─┘└───────┘└┘└─────┘└┘└────────┘└┘└─────────┘└┘└─────┘  └──┘└─┘└┘  └───┘  └────
typ  ─┘└───────┘└┘└─────┘└┘└────────┘└┘└─────────┘└┘└─────┘  └──┘└─┘└┘  └───┘  └────
doc  ─┘         └┘       └┘          └┘           └┘         └──┘   └┘  └───┘  └────
txt  ─┘         └┘       └┘          └┘           └┘         └──┘   └┘  └───┘  └────
par  ─┘         └┘       └┘          └┘           └┘         └──┘   └┘  └───┘  └────
pid  ─┘         └┘       └┘          └┘           └┘         └──┘   └┘             
st   ────────────────────────────────────────────────────────────────────────────────
2469  
src  
typ  
doc  
txt  
par  
pid  
st   
2470  @[simp] theorem sublists_concat (l : list α) (a : α) :
id                                        └──┘        
src                                       └──┘
typ                                       └──┘        
doc    └──┘
2471    sublists (l ++ [a]) = sublists l ++ map (λ x, x ++ [a]) (sublists l) :=
id     └──────┘   └┘    └──────┘  └┘ └─┘       └┘    └──────┘ 
src    └──────┘    └┘     └──────┘   └┘ └─┘         └┘     └──────┘
typ    └──────┘   └┘    └──────┘  └┘ └─┘       └┘    └──────┘ 
doc    └──────┘              └──────┘                           └──────┘
2472  by rw [sublists_append, sublists_singleton, bind_eq_bind, cons_bind, cons_bind, nil_bind,
id          └─────────────┘  └────────────────┘  └──────────┘  └───────┘  └───────┘  └──────┘
src     └──┘└─────────────┘└┘└────────────────┘└┘└──────────┘└┘└───────┘└┘└───────┘└┘└──────┘└─
typ     └──┘└─────────────┘└┘└────────────────┘└┘└──────────┘└┘└───────┘└┘└───────┘└┘└──────┘└─
doc     └──┘               └┘                  └┘            └┘         └┘         └┘        └─
txt     └──┘               └┘                  └┘            └┘         └┘         └┘        └─
par     └──┘               └┘                  └┘            └┘         └┘         └┘        └─
pid       └┘               └┘                  └┘            └┘         └┘         └┘        └─
st     └──────────────────┘└──────────────────┘└────────────┘└─────────┘└─────────┘└────────┘└─
2473    map_eq_map, map_eq_map, map_id' (append_nil), append_nil]
id     └────────┘  └────────┘  └─────┘  └────────┘   └────────┘
src  ─┘└────────┘└┘└────────┘└┘└─────┘ └────────┘└─┘└────────┘└─
typ  ─┘└────────┘└┘└────────┘└┘└─────┘ └────────┘└─┘└────────┘└─
doc  ─┘          └┘          └┘                  └─┘          └─
txt  ─┘          └┘          └┘                  └─┘          └─
par  ─┘          └┘          └┘                  └─┘          └─
pid  ─┘          └┘          └┘                  └─┘          
st   ───────────┘└──────────┘└────────────────────┘└──────────┘
2474  
src  
typ  
doc  
txt  
par  
pid  
st   
2475  theorem sublists_reverse (l : list α) : sublists (reverse l) = map reverse (sublists' l) :=
id                                 └──┘     └──────┘  └─────┘    └─┘ └─────┘  └───────┘ 
src                                └──┘      └──────┘  └─────┘     └─┘ └─────┘  └───────┘
typ                                └──┘     └──────┘  └─────┘    └─┘ └─────┘  └───────┘ 
doc                                          └──────┘                            └───────┘
2476  by induction l with hd tl ih; [refl,
id                                
src     └────────┘ └────────────┘  └──┘
typ     └────────┘└────────────┘  └──┘
doc     └────────┘ └────────────┘   └──┘
txt     └────────┘ └────────────┘   └──┘
par     └────────┘ └────────────┘   └──┘
pid               └───────────┘
st     └──────────────────────────────────
2477  simp only [reverse_cons, sublists_append, sublists'_cons, map_append, ih, sublists_singleton,
id              └──────────┘  └─────────────┘  └────────────┘  └────────┘  └┘  └────────────────┘
src  └─────────┘└──────────┘└┘└─────────────┘└┘└────────────┘└┘└────────┘└┘  └┘└────────────────┘└─
typ  └─────────┘└──────────┘└┘└─────────────┘└┘└────────────┘└┘└────────┘└┘└┘└┘└────────────────┘└─
doc  └─────────┘            └┘               └┘              └┘          └┘  └┘                  └─
txt  └─────────┘            └┘               └┘              └┘          └┘  └┘                  └─
par  └─────────┘            └┘               └┘              └┘          └┘  └┘                  └─
pid      └──┘└┘            └┘               └┘              └┘          └┘  └┘                  └─
st   ──────────────────────────────────────────────────────────────────────────────────────────────
2478    map_eq_map, bind_eq_bind, map_map, cons_bind, append_nil, nil_bind, (∘)]]
id     └────────┘  └──────────┘  └─────┘  └───────┘  └────────┘  └──────┘  
src  ─┘└────────┘└┘└──────────┘└┘└─────┘└┘└───────┘└┘└────────┘└┘└──────┘└┘└─┘
typ  ─┘└────────┘└┘└──────────┘└┘└─────┘└┘└───────┘└┘└────────┘└┘└──────┘└┘└─┘
doc  ─┘          └┘            └┘       └┘         └┘          └┘        └┘ └─┘
txt  ─┘          └┘            └┘       └┘         └┘          └┘        └┘ └─┘
par  ─┘          └┘            └┘       └┘         └┘          └┘        └┘ └─┘
pid  ─┘          └┘            └┘       └┘         └┘          └┘        └┘ └─┘
st   ──────────────────────────────────────────────────────────────────────────┘
2479  
2480  theorem sublists_eq_sublists' (l : list α) : sublists l = map reverse (sublists' (reverse l)) :=
id                                      └──┘     └──────┘   └─┘ └─────┘  └───────┘  └─────┘ 
src                                     └──┘      └──────┘    └─┘ └─────┘  └───────┘  └─────┘
typ                                     └──┘     └──────┘   └─┘ └─────┘  └───────┘  └─────┘ 
doc                                               └──────┘                  └───────┘
2481  by rw [← sublists_reverse, reverse_reverse]
id            └──────────────┘  └─────────────┘
src     └────┘└──────────────┘└┘└─────────────┘└─
typ     └────┘└──────────────┘└┘└─────────────┘└─
doc     └────┘                └┘               └─
txt     └────┘                └┘               └─
par     └────┘                └┘               └─
pid       └──┘                └┘               
st     └─────────────────────┘└───────────────┘
2482  
src  
typ  
doc  
txt  
par  
pid  
st   
2483  theorem sublists'_reverse (l : list α) : sublists' (reverse l) = map reverse (sublists l) :=
id                                  └──┘     └───────┘  └─────┘    └─┘ └─────┘  └──────┘ 
src                                 └──┘      └───────┘  └─────┘     └─┘ └─────┘  └──────┘
typ                                 └──┘     └───────┘  └─────┘    └─┘ └─────┘  └──────┘ 
doc                                           └───────┘                            └──────┘
2484  by simp only [sublists_eq_sublists', map_map, map_id' (reverse_reverse)]
id                 └───────────────────┘  └─────┘  └─────┘  └─────────────┘
src     └─────────┘└───────────────────┘└┘└─────┘└┘└─────┘ └─────────────┘└──
typ     └─────────┘└───────────────────┘└┘└─────┘└┘└─────┘ └─────────────┘└──
doc     └─────────┘                     └┘       └┘                       └──
txt     └─────────┘                     └┘       └┘                       └──
par     └─────────┘                     └┘       └┘                       └──
pid         └──┘└┘                     └┘       └┘                       └┘
st     └──────────────────────────────────────────────────────────────────────
2485  
src  
typ  
doc  
txt  
par  
pid  
st   
2486  theorem sublists'_eq_sublists (l : list α) : sublists' l = map reverse (sublists (reverse l)) :=
id                                      └──┘     └───────┘   └─┘ └─────┘  └──────┘  └─────┘ 
src                                     └──┘      └───────┘    └─┘ └─────┘  └──────┘  └─────┘
typ                                     └──┘     └───────┘   └─┘ └─────┘  └──────┘  └─────┘ 
doc                                               └───────┘                  └──────┘
2487  by rw [← sublists'_reverse, reverse_reverse]
id            └───────────────┘  └─────────────┘
src     └────┘└───────────────┘└┘└─────────────┘└─
typ     └────┘└───────────────┘└┘└─────────────┘└─
doc     └────┘                 └┘               └─
txt     └────┘                 └┘               └─
par     └────┘                 └┘               └─
pid       └──┘                 └┘               
st     └──────────────────────┘└───────────────┘
2488  
src  
typ  
doc  
txt  
par  
pid  
st   
2489  theorem sublists_aux_ne_nil : ∀ (l : list α), [] ∉ sublists_aux l cons
id                                       └──┘    └┘  └──────────┘  └──┘
src                                       └──┘     └┘  └──────────┘   └──┘
typ                                      └──┘    └┘  └──────────┘  └──┘
2490  | [] := id
id     └┘    └┘
src    └┘    └┘
typ    └┘    └┘
2491  | (a::l) := begin
id       └┘
src      └┘
typ      └┘
st               └─────
2492    rw [sublists_aux_cons_cons],
id         └────────────────────┘
src    └──┘└────────────────────┘
typ    └──┘└────────────────────┘
doc    └──┘                      
txt    └──┘                      
par    └──┘                      
pid      └┘                      
st   ───────────────────────────┘└──
2493    refine not_mem_cons_of_ne_of_not_mem (cons_ne_nil _ _).symm _,
id            └───────────────────────────┘  └─────────┘
src    └─────┘└───────────────────────────┘ └─────────┘└──────────┘
typ    └─────┘└───────────────────────────┘ └─────────┘└──────────┘
doc    └─────┘                                         └──────────┘
txt    └─────┘                                         └──────────┘
par    └─────┘                                         └──────────┘
pid                                                   └──────────┘
st   ──────────────────────────────────────────────────────────────┘└─
2494    have := sublists_aux_ne_nil l, revert this,
id             └─────────────────┘ 
src    └──────┘                      └─────────┘
typ    └──────┘└─────────────────┘  └─────────┘
doc    └──────┘                      └─────────┘
txt    └──────┘                      └─────────┘
par    └──────┘                      └─────────┘
pid    └───┘└─┘                            └───┘
st   ──────────────────────────────┘└───────────┘└─
2495    induction sublists_aux l cons; intro, {rwa foldr},
id               └──────────┘  └──┘              └───┘
src    └────────┘└──────────┘ └──┘  └───┘   └──┘└───┘
typ    └────────┘└──────────┘└──┘  └───┘   └──┘└───┘
doc    └────────┘                   └───┘   └──┘
txt    └────────┘                   └───┘   └──┘
par    └────────┘                   └───┘   └──┘
pid                                           
st   ─────────────────────────────────────┘└─────┘└───┘└┘
2496    simp only [foldr, mem_cons_iff, false_or, not_or_distrib],
id                └───┘  └──────────┘  └──────┘  └────────────┘
src    └─────────┘└───┘└┘└──────────┘└┘└──────┘└┘└────────────┘
typ    └─────────┘└───┘└┘└──────────┘└┘└──────┘└┘└────────────┘
doc    └─────────┘     └┘            └┘        └┘              
txt    └─────────┘     └┘            └┘        └┘              
par    └─────────┘     └┘            └┘        └┘              
pid        └──┘└┘     └┘            └┘        └┘              
st   ──────────────────────────────────────────────────────────┘└─
2497    exact ⟨ne_of_not_mem_cons this, ih (not_mem_of_not_mem_cons this)⟩
id            └────────────────┘       └┘  └─────────────────────┘ └──┘
src    └────┘ └────────────────┘    └┘   └─────────────────────┘    └─┘
typ    └────┘ └────────────────┘    └┘└┘ └─────────────────────┘└──┘└─┘
doc    └────┘                       └┘                              └─┘
txt    └────┘                       └┘                              └─┘
par    └────┘                       └┘                              └─┘
pid                                └┘                              └┘
st   ────────────────────────────────────────────────────────────────────┘
2498  end
st   └─┘
2499  
2500  @[simp] theorem mem_sublists {s t : list α} : s ∈ sublists t ↔ s <+ t :=
id                                       └──┘       └──────┘    └┘ 
src                                      └──┘         └──────┘      └┘
typ                                      └──┘       └──────┘    └┘ 
doc    └──┘                                            └──────┘
2501  by rw [← reverse_sublist_iff, ← mem_sublists',
id            └─────────────────┘    └───────────┘
src     └────┘└─────────────────┘└──┘└───────────┘└─
typ     └────┘└─────────────────┘└──┘└───────────┘└─
doc     └────┘                   └──┘             └─
txt     └────┘                   └──┘             └─
par     └────┘                   └──┘             └─
pid       └──┘                   └──┘             └─
st     └────────────────────────┘└───────────────┘└─
2502         sublists'_reverse, mem_map_of_inj reverse_injective]
id          └───────────────┘  └────────────┘ └───────────────┘
src  ──────┘└───────────────┘└┘└────────────┘└───────────────┘└─
typ  ──────┘└───────────────┘└┘└────────────┘└───────────────┘└─
doc  ──────┘                 └┘                               └─
txt  ──────┘                 └┘                               └─
par  ──────┘                 └┘                               └─
pid  ──────┘                 └┘                               
st   ───────────────────────┘└────────────────────────────────┘
2503  
src  
typ  
doc  
txt  
par  
pid  
st   
2504  @[simp] theorem length_sublists (l : list α) : length (sublists l) = 2 ^ length l :=
id                                        └──┘     └────┘  └──────┘       └────┘ 
src                                       └──┘      └────┘  └──────┘        └────┘
typ                                       └──┘     └────┘  └──────┘       └────┘ 
doc    └──┘                                                 └──────┘
2505  by simp only [sublists_eq_sublists', length_map, length_sublists', length_reverse]
id                 └───────────────────┘  └────────┘  └──────────────┘  └────────────┘
src     └─────────┘└───────────────────┘└┘└────────┘└┘└──────────────┘└┘└────────────┘└─
typ     └─────────┘└───────────────────┘└┘└────────┘└┘└──────────────┘└┘└────────────┘└─
doc     └─────────┘                     └┘          └┘                └┘              └─
txt     └─────────┘                     └┘          └┘                └┘              └─
par     └─────────┘                     └┘          └┘                └┘              └─
pid         └──┘└┘                     └┘          └┘                └┘              
st     └────────────────────────────────────────────────────────────────────────────────
2506  
src  
typ  
doc  
txt  
par  
pid  
st   
2507  theorem map_ret_sublist_sublists (l : list α) : map list.ret l <+ sublists l :=
id                                         └──┘     └─┘ └──────┘  └┘ └──────┘ 
src                                        └──┘      └─┘ └──────┘   └┘ └──────┘
typ                                        └──┘     └─┘ └──────┘  └┘ └──────┘ 
doc                                                                    └──────┘
2508  reverse_rec_on l (nil_sublist _) $
id   └────────────┘   └─────────┘
src  └────────────┘    └─────────┘
typ  └────────────┘   └─────────┘
2509  λ l a IH, by simp only [map, map_append, sublists_concat]; exact
id       └┘                └─┘  └────────┘  └─────────────┘
src               └─────────┘└─┘└┘└────────┘└┘└─────────────┘  └────┘
typ      └┘     └─────────┘└─┘└┘└────────┘└┘└─────────────┘  └────┘
doc               └─────────┘   └┘          └┘                 └────┘
txt               └─────────┘   └┘          └┘                 └────┘
par               └─────────┘   └┘          └┘                 └────┘
pid                   └──┘└┘   └┘          └┘                      
st               └────────────────────────────────────────────────────
2510  ((append_sublist_append_left _).2 $ singleton_sublist.2 $
id     └────────────────────────┘        └───────────────┘
src    └────────────────────────┘└────┘ └───────────────┘└─┘ 
typ    └────────────────────────┘└────┘ └───────────────┘└─┘ 
doc                              └────┘                  └─┘ 
txt                              └────┘                  └─┘ 
par                              └────┘                  └─┘ 
pid                              └────┘                  └─┘ 
st   ──────────────────────────────────────────────────────────
2511    mem_map.2 ⟨[], mem_sublists.2 (nil_sublist _), by refl⟩).trans
id     └─────┘        └──────────┘    └─────────┘
src  ─┘└─────┘└─┘   └┘└──────────┘└─┘ └─────────┘└───┘  └──┘└───────┘
typ  ─┘└─────┘└─┘   └┘└──────────┘└─┘ └─────────┘└───┘  └──┘└───────┘
doc  ─┘       └─┘   └┘            └─┘            └───┘  └──┘└───────┘
txt  ─┘       └─┘   └┘            └─┘            └───┘  └──┘└───────┘
par  ─┘       └─┘   └┘            └─┘            └───┘  └──┘└───────┘
pid  ─┘       └─┘   └┘            └─┘            └───┘  └────────────┘
st   ──────────────────────────────────────────────────┘└───┘└────────
2512  ((append_sublist_append_right _).2 IH)
id     └─────────────────────────┘      └┘
src    └─────────────────────────┘└────┘  └─
typ    └─────────────────────────┘└────┘└┘└─
doc                               └────┘  └─
txt                               └────┘  └─
par                               └────┘  └─
pid                               └────┘  
st   ───────────────────────────────────────
2513  
src  
typ  
doc  
txt  
par  
pid  
st   
2514  /- sublists_len -/
src  ───────────────────
typ  ───────────────────
doc  ───────────────────
txt  ───────────────────
par  ───────────────────
pid  ───────────────────
st   ───────────────────
2515  
src  
typ  
doc  
txt  
par  
pid  
st   
2516  def sublists_len_aux {α β : Type*} : ℕ → list α → (list α → β) → list β → list β
id                                          └──┘     └──┘       └──┘    └──┘ 
src                                          └──┘      └──┘          └──┘     └──┘
typ                                         └──┘     └──┘       └──┘    └──┘ 
2517  | 0     l      f r := f [] :: r
id                         └┘ └┘
src                          └┘ └┘
typ                        └┘ └┘
2518  | (n+1) []     f r := r
id          └┘       
src         └┘
typ         └┘       
2519  | (n+1) (a::l) f r := sublists_len_aux (n + 1) l f
id          └┘       └──────────────┘    
src           └┘                              
typ         └┘       └──────────────┘    
2520    (sublists_len_aux n l (f ∘ list.cons a) r)
id      └──────────────┘         └───────┘
src                              └───────┘
typ     └──────────────┘         └───────┘
2521  
2522  def sublists_len {α : Type*} (n : ℕ) (l : list α) : list (list α) :=
id                                            └──┘     └──┘  └──┘ 
src                                           └──┘      └──┘  └──┘
typ                                           └──┘     └──┘  └──┘ 
2523  sublists_len_aux n l id []
id   └──────────────┘   └┘ └┘
src  └──────────────┘     └┘ └┘
typ  └──────────────┘   └┘ └┘
2524  
2525  lemma sublists_len_aux_append {α β γ : Type*} :
2526    ∀ (n : ℕ) (l : list α) (f : list α → β) (g : β → γ) (r : list β) (s : list γ),
id                  └──┘        └──┘                   └──┘        └──┘ 
src                  └──┘         └──┘                         └──┘         └──┘
typ                 └──┘        └──┘                   └──┘        └──┘ 
2527    sublists_len_aux n l (g ∘ f) (r.map g ++ s) =
id     └──────────────┘         └──┘  └┘   
src    └──────────────┘              └──┘   └┘    
typ    └──────────────┘         └──┘  └┘   
2528    (sublists_len_aux n l f r).map g ++ s
id      └──────────────┘     └─┘   └┘ 
src     └──────────────┘         └─┘    └┘
typ     └──────────────┘     └─┘   └┘ 
2529  | 0     l      f g r s := rfl
id                             └─┘
src                            └─┘
typ                            └─┘
2530  | (n+1) []     f g r s := rfl
id          └┘                └─┘
src         └┘                └─┘
typ         └┘                └─┘
2531  | (n+1) (a::l) f g r s := begin
id            └┘
src           └┘
typ           └┘
st                             └─────
2532    unfold sublists_len_aux,
src    └─────────────────────┘
typ    └─────────────────────┘
doc    └─────────────────────┘
txt    └─────────────────────┘
par    └─────────────────────┘
pid          └───────────────┘
st   ────────────────────────┘└─
2533    rw [show ((g ∘ f) ∘ list.cons a) = (g ∘ f ∘ list.cons a), by refl,
id                                             └───────┘ 
src    └──┘        └┘           └┘     └───────┘ └────┘└──┘└─
typ    └──┘        └┘           └┘   └───────┘└────┘└──┘└─
doc    └──┘         └┘           └┘                └────┘└──┘└─
txt    └──┘         └┘           └┘                └────┘└──┘└─
par    └──┘         └┘           └┘                └────┘└──┘└─
pid      └┘         └┘           └┘                └───────────
st   ─────────────────────────────────────────────────────────────┘└───┘└─
2534      sublists_len_aux_append, sublists_len_aux_append]
id       └─────────────────────┘  └─────────────────────┘
src  ───┘                       └┘                       └┘
typ  ───┘└─────────────────────┘└┘└─────────────────────┘└┘
doc  ───┘                       └┘                       └┘
txt  ───┘                       └┘                       └┘
par  ───┘                       └┘                       └┘
pid  ───┘                       └┘                       
st   ──────────────────────────┘└───────────────────────┘
2535  end
st   └─┘
2536  
2537  lemma sublists_len_aux_eq {α β : Type*} (l : list α) (n) (f : list α → β) (r) :
id                                                └──┘            └──┘    
src                                               └──┘             └──┘
typ                                               └──┘            └──┘    
2538    sublists_len_aux n l f r = (sublists_len n l).map f ++ r :=
id     └──────────────┘       └──────────┘   └─┘   └┘ 
src    └──────────────┘           └──────────┘     └─┘    └┘
typ    └──────────────┘       └──────────┘   └─┘   └┘ 
2539  by rw [sublists_len, ← sublists_len_aux_append]; refl
id          └──────────┘    └─────────────────────┘
src     └──┘└──────────┘└──┘└─────────────────────┘  └────
typ     └──┘└──────────┘└──┘└─────────────────────┘  └────
doc     └──┘            └──┘                         └────
txt     └──┘            └──┘                         └────
par     └──┘            └──┘                         └────
pid       └┘            └──┘                             
st     └───────────────┘└─────────────────────────┘└──────
2540  
src  
typ  
doc  
txt  
par  
pid  
st   
2541  lemma sublists_len_aux_zero {α : Type*} (l : list α) (f : list α → β) (r) :
id                                                └──┘        └──┘    
src                                               └──┘         └──┘
typ                                               └──┘        └──┘    
2542    sublists_len_aux 0 l f r = f [] :: r := by cases l; refl
id     └──────────────┘        └┘ └┘              
src    └──────────────┘            └┘ └┘         └────┘   └────
typ    └──────────────┘        └┘ └┘        └────┘  └────
doc                                               └────┘   └────
txt                                               └────┘   └────
par                                               └────┘   └────
pid                                                           
st                                               └──────────────
2543  
src  
typ  
doc  
txt  
par  
pid  
st   
2544  @[simp] lemma sublists_len_zero {α : Type*} (l : list α) :
id                                                    └──┘ 
src                                                   └──┘
typ                                                   └──┘ 
doc    └──┘
2545    sublists_len 0 l = [[]] := sublists_len_aux_zero _ _ _
id     └──────────┘     └┘    └───────────────────┘
src    └──────────┘      └──┘    └───────────────────┘
typ    └──────────┘     └┘    └───────────────────┘
2546  
2547  @[simp] lemma sublists_len_succ_nil {α : Type*} (n) :
doc    └──┘
2548    sublists_len (n+1) (@nil α) = [] := rfl
id     └──────────┘       └─┘    └┘    └─┘
src    └──────────┘        └─┘     └┘    └─┘
typ    └──────────┘       └─┘    └┘    └─┘
2549  
2550  @[simp] lemma sublists_len_succ_cons {α : Type*} (n) (a : α) (l) :
id                                                             
typ                                                            
doc    └──┘
2551    sublists_len (n + 1) (a::l) =
id     └──────────┘        └┘  
src    └──────────┘          └┘   
typ    └──────────┘        └┘  
2552    sublists_len (n + 1) l ++ (sublists_len n l).map (cons a) :=
id     └──────────┘        └┘  └──────────┘   └─┘   └──┘ 
src    └──────────┘          └┘  └──────────┘     └─┘   └──┘
typ    └──────────┘        └┘  └──────────┘   └─┘   └──┘ 
2553  by rw [sublists_len, sublists_len_aux, sublists_len_aux_eq,
id          └──────────┘  └──────────────┘  └─────────────────┘
src     └──┘└──────────┘└┘└──────────────┘└┘└─────────────────┘└─
typ     └──┘└──────────┘└┘└──────────────┘└┘└─────────────────┘└─
doc     └──┘            └┘                └┘                   └─
txt     └──┘            └┘                └┘                   └─
par     └──┘            └┘                └┘                   └─
pid       └┘            └┘                └┘                   └─
st     └───────────────┘└────────────────┘└───────────────────┘└─
2554    sublists_len_aux_eq, map_id, append_nil]; refl
id     └─────────────────┘  └────┘  └────────┘
src  ─┘└─────────────────┘└┘└────┘└┘└────────┘  └────
typ  ─┘└─────────────────┘└┘└────┘└┘└────────┘  └────
doc  ─┘                   └┘      └┘            └────
txt  ─┘                   └┘      └┘            └────
par  ─┘                   └┘      └┘            └────
pid  ─┘                   └┘      └┘                
st   ────────────────────┘└──────┘└──────────┘└──────
2555  
src  
typ  
doc  
txt  
par  
pid  
st   
2556  @[simp] lemma length_sublists_len {α : Type*} : ∀ n (l : list α),
id                                                           └──┘ 
src                                                           └──┘
typ                                                          └──┘ 
doc    └──┘
2557    length (sublists_len n l) = nat.choose (length l) n
id     └────┘  └──────────┘     └────────┘  └────┘   
src    └────┘  └──────────┘       └────────┘  └────┘
typ    └────┘  └──────────┘     └────────┘  └────┘   
doc                                └────────┘
2558  | 0     l      := by simp
src                       └───┘
typ                       └───┘
doc                       └───┘
txt                       └───┘
par                       └───┘
pid                           
st                       └────┘
2559  | (n+1) []     := by simp
id          └┘
src         └┘           └───┘
typ         └┘           └───┘
doc                       └───┘
txt                       └───┘
par                       └───┘
pid                           
st                       └────┘
2560  | (n+1) (a::l) := by simp [-add_comm, nat.choose, *]; apply add_comm
id            └┘                          └────────┘            └──────┘
src           └┘         └───────────────┘└────────┘└──┘  └────┘└──────┘
typ           └┘         └───────────────┘└────────┘└──┘  └────┘└──────┘
doc                       └───────────────┘└────────┘└──┘  └────┘        
txt                       └───────────────┘          └──┘  └────┘        
par                       └───────────────┘          └──┘  └────┘        
pid                           └──────────┘          └──┘               
st                       └────────────────────────────────────────────────
2561  
src  
typ  
doc  
txt  
par  
pid  
st   
2562  lemma sublists_len_sublist_sublists' {α : Type*} : ∀ n (l : list α),
id                                                              └──┘ 
src                                                              └──┘
typ                                                             └──┘ 
2563    sublists_len n l <+ sublists' l
id     └──────────┘   └┘ └───────┘ 
src    └──────────┘     └┘ └───────┘
typ    └──────────┘   └┘ └───────┘ 
doc                        └───────┘
2564  | 0     l      := singleton_sublist.2 (mem_sublists'.2 (nil_sublist _))
id                     └───────────────┘   └───────────┘   └─────────┘
src                    └───────────────┘   └───────────┘   └─────────┘
typ                    └───────────────┘   └───────────┘   └─────────┘
2565  | (n+1) []     := nil_sublist _
id          └┘        └─────────┘
src         └┘        └─────────┘
typ         └┘        └─────────┘
2566  | (n+1) (a::l) := begin
id            └┘
src           └┘
typ           └┘
st                     └─────
2567    rw [sublists_len_succ_cons, sublists'_cons],
id         └────────────────────┘  └────────────┘
src    └──┘└────────────────────┘└┘└────────────┘
typ    └──┘└────────────────────┘└┘└────────────┘
doc    └──┘                      └┘              
txt    └──┘                      └┘              
par    └──┘                      └┘              
pid      └┘                      └┘              
st   ───────────────────────────┘└──────────────┘└──
2568    exact append_sublist_append
id           └───────────────────┘
src    └────┘└───────────────────┘
typ    └────┘└───────────────────┘
doc    └────┘                     
txt    └────┘                     
par    └────┘                     
pid                              
st   ──────────────────────────────
2569      (sublists_len_sublist_sublists' _ _)
src  ───┘                               └─────
typ  ───┘                               └─────
doc  ───┘                               └─────
txt  ───┘                               └─────
par  ───┘                               └─────
pid  ───┘                               └─────
st   ─────────────────────────────────────────
2570      (map_sublist_map _ (sublists_len_sublist_sublists' _ _))
id        └─────────────┘    └────────────────────────────┘
src  ───┘ └─────────────┘└─┘                               └─────┘
typ  ───┘ └─────────────┘└─┘ └────────────────────────────┘└─────┘
doc  ───┘                └─┘                               └─────┘
txt  ───┘                └─┘                               └─────┘
par  ───┘                └─┘                               └─────┘
pid  ───┘                └─┘                               └────┘
st   ────────────────────────────────────────────────────────────┘
2571  end
st   └─┘
2572  
2573  lemma sublists_len_sublist_of_sublist
2574    {α : Type*} (n) {l₁ l₂ : list α} (h : l₁ <+ l₂) : sublists_len n l₁ <+ sublists_len n l₂ :=
id                              └──┘        └┘ └┘ └┘    └──────────┘  └┘ └┘ └──────────┘  └┘
src                             └──┘            └┘       └──────────┘      └┘ └──────────┘
typ                             └──┘        └┘ └┘ └┘    └──────────┘  └┘ └┘ └──────────┘  └┘
2575  begin
st   └─────
2576    induction n with n IHn generalizing l₁ l₂, {simp},
id               
src    └────────┘ └────────────────────────────┘   └──┘
typ    └────────┘└────────────────────────────┘   └──┘
doc    └────────┘ └────────────────────────────┘   └──┘
txt    └────────┘ └────────────────────────────┘   └──┘
par    └────────┘ └────────────────────────────┘   └──┘
pid              └────────┘└─────────────────┘
st   ──────────────────────────────────────────┘└─────┘└┘
2577    induction h with l₁ l₂ a s IH l₁ l₂ a s IH, {refl},
id               
src    └────────┘ └─────────────────────────────┘   └──┘
typ    └────────┘└─────────────────────────────┘   └──┘
doc    └────────┘ └─────────────────────────────┘   └──┘
txt    └────────┘ └─────────────────────────────┘   └──┘
par    └────────┘ └─────────────────────────────┘   └──┘
pid              └────────────────────────────┘
st   ───────────────────────────────────────────┘└─────┘└┘
2578    { refine IH.trans _,
id              └──────┘
src      └─────┘└──────┘└┘
typ      └─────┘└──────┘└┘
doc      └─────┘        └┘
txt      └─────┘        └┘
par      └─────┘        └┘
pid                    └┘
st   ───┘└───────────────┘└─
2579      rw sublists_len_succ_cons,
id          └────────────────────┘
src      └─┘└────────────────────┘
typ      └─┘└────────────────────┘
doc      └─┘
txt      └─┘
par      └─┘
pid        
st   ────────────────────────────┘└─
2580      apply sublist_append_left },
id             └─────────────────┘
src      └────┘└─────────────────┘
typ      └────┘└─────────────────┘
doc      └────┘                   
txt      └────┘                   
par      └────┘                   
pid                              
st   ─────────────────────────────┘└┘
2581    { simp [sublists_len_succ_cons],
id             └────────────────────┘
src      └────┘└────────────────────┘
typ      └────┘└────────────────────┘
doc      └────┘                      
txt      └────┘                      
par      └────┘                      
pid                                
st   ────────────────────────────────┘└─
2582      exact append_sublist_append IH (map_sublist_map _ (IHn s)) }
id             └───────────────────┘ └┘  └─────────────┘    └─┘ 
src      └────┘└───────────────────┘   └─────────────┘└─┘     └─┘
typ      └────┘└───────────────────┘└┘ └─────────────┘└─┘ └─┘└─┘
doc      └────┘                                       └─┘     └─┘
txt      └────┘                                       └─┘     └─┘
par      └────┘                                       └─┘     └─┘
pid                                                  └─┘     └┘
st   ──────────────────────────────────────────────────────────────┘└─
2583  end
st   ──┘
2584  
2585  lemma length_of_sublists_len {α : Type*} : ∀ {n} {l l' : list α},
id                                                          └──┘ 
src                                                           └──┘
typ                                                         └──┘ 
2586    l' ∈ sublists_len n l → length l' = n
id     └┘  └──────────┘     └────┘ └┘  
src        └──────────┘       └────┘    
typ    └┘  └──────────┘     └────┘ └┘  
2587  | 0     l      l' (or.inl rfl) := rfl
id                      └────┘ └─┘     └─┘
src                     └────┘ └─┘     └─┘
typ                     └────┘ └─┘     └─┘
2588  | (n+1) (a::l) l' h := begin
id            └┘
src           └┘
typ           └┘
st                          └─────
2589    rw [sublists_len_succ_cons, mem_append, mem_map] at h,
id         └────────────────────┘  └────────┘  └─────┘
src    └──┘└────────────────────┘└┘└────────┘└┘└─────┘└────┘
typ    └──┘└────────────────────┘└┘└────────┘└┘└─────┘└────┘
doc    └──┘                      └┘          └┘       └────┘
txt    └──┘                      └┘          └┘       └────┘
par    └──┘                      └┘          └┘       └────┘
pid      └┘                      └┘          └┘       └───┘
st   ───────────────────────────┘└──────────┘└───────┘└───┘└─
2590    rcases h with h | ⟨l', h, rfl⟩,
id            
src    └─────┘ └────────────────────┘
typ    └─────┘└────────────────────┘
doc    └─────┘ └────────────────────┘
txt    └─────┘ └────────────────────┘
par    └─────┘ └────────────────────┘
pid           └────────────────────┘
st   ───────────────────────────────┘└─
2591    { exact length_of_sublists_len h },
id             └────────────────────┘ 
src      └────┘                       
typ      └────┘└────────────────────┘
doc      └────┘                       
txt      └────┘                       
par      └────┘                       
pid                                  
st   ───┘└─────────────────────────────┘└┘
2592    { exact congr_arg (+1) (length_of_sublists_len h) },
id             └───────┘      └────────────────────┘ 
src      └────┘└───────┘└──┘                        └┘
typ      └────┘└───────┘└──┘ └────────────────────┘└┘
doc      └────┘          └──┘                        └┘
txt      └────┘          └──┘                        └┘
par      └────┘          └──┘                        └┘
pid                     └──┘                        
st   ───────────────────────────────────────────────────┘└──
2593  end
st   ──┘
2594  
2595  lemma mem_sublists_len_self {α : Type*} {l l' : list α}
id                                                   └──┘ 
src                                                  └──┘
typ                                                  └──┘ 
2596    (h : l' <+ l) : l' ∈ sublists_len (length l') l :=
id          └┘ └┘     └┘  └──────────┘  └────┘ └┘  
src            └┘          └──────────┘  └────┘
typ         └┘ └┘     └┘  └──────────┘  └────┘ └┘  
2597  begin
st   └─────
2598    induction h with l₁ l₂ a s IH l₁ l₂ a s IH,
id               
src    └────────┘ └─────────────────────────────┘
typ    └────────┘└─────────────────────────────┘
doc    └────────┘ └─────────────────────────────┘
txt    └────────┘ └─────────────────────────────┘
par    └────────┘ └─────────────────────────────┘
pid              └────────────────────────────┘
st   ───────────────────────────────────────────┘└─
2599    { exact or.inl rfl },
id             └────┘ └─┘
src      └────┘└────┘└─┘
typ      └────┘└────┘└─┘
doc      └────┘         
txt      └────┘         
par      └────┘         
pid                    
st   ───┘└───────────────┘└┘
2600    { cases l₁ with b l₁,
id             └┘
src      └────┘  └────────┘
typ      └────┘└┘└────────┘
doc      └────┘  └────────┘
txt      └────┘  └────────┘
par      └────┘  └────────┘
pid             └────────┘
st   ───┘└────────────────┘└─
2601      { exact or.inl rfl },
id               └────┘ └─┘
src        └────┘└────┘└─┘
typ        └────┘└────┘└─┘
doc        └────┘         
txt        └────┘         
par        └────┘         
pid                      
st   ─────┘└───────────────┘└┘
2602      { rw [length, sublists_len_succ_cons],
id             └────┘  └────────────────────┘
src        └──┘└────┘└┘└────────────────────┘
typ        └──┘└────┘└┘└────────────────────┘
doc        └──┘      └┘                      
txt        └──┘      └┘                      
par        └──┘      └┘                      
pid          └┘      └┘                      
st   ───────────────┘└──────────────────────┘└─
2603        exact mem_append_left _ IH } },
id               └─────────────┘   └┘
src        └────┘└─────────────┘└─┘  
typ        └────┘└─────────────┘└─┘└┘
doc        └────┘               └─┘  
txt        └────┘               └─┘  
par        └────┘               └─┘  
pid                            └─┘  
st   ────────────────────────────────┘└──┘
2604    { rw [length, sublists_len_succ_cons],
id           └────┘  └────────────────────┘
src      └──┘└────┘└┘└────────────────────┘
typ      └──┘└────┘└┘└────────────────────┘
doc      └──┘      └┘                      
txt      └──┘      └┘                      
par      └──┘      └┘                      
pid        └┘      └┘                      
st   ─────────────┘└──────────────────────┘└─
2605      exact mem_append_right _ (mem_map.2 ⟨_, IH, rfl⟩) }
id             └──────────────┘    └─────┘       └┘  └─┘
src      └────┘└──────────────┘└─┘ └─────┘└─┘ └─┘  └┘└─┘└─┘
typ      └────┘└──────────────┘└─┘ └─────┘└─┘ └─┘└┘└┘└─┘└─┘
doc      └────┘                └─┘        └─┘ └─┘  └┘   └─┘
txt      └────┘                └─┘        └─┘ └─┘  └┘   └─┘
par      └────┘                └─┘        └─┘ └─┘  └┘   └─┘
pid                           └─┘        └─┘ └─┘  └┘   └┘
st   ─────────────────────────────────────────────────────┘└─
2606  end
st   ──┘
2607  
2608  @[simp] lemma mem_sublists_len {α : Type*} {n} {l l' : list α} :
id                                                          └──┘ 
src                                                         └──┘
typ                                                         └──┘ 
doc    └──┘
2609    l' ∈ sublists_len n l ↔ l' <+ l ∧ length l' = n :=
id     └┘  └──────────┘    └┘ └┘   └────┘ └┘  
src        └──────────┘         └┘    └────┘    
typ    └┘  └──────────┘    └┘ └┘   └────┘ └┘  
2610  ⟨λ h, ⟨mem_sublists'.1
id         └───────────┘
src         └───────────┘
typ        └───────────┘
2611      (subset_of_sublist (sublists_len_sublist_sublists' _ _) h),
id        └───────────────┘  └────────────────────────────┘      
src       └───────────────┘  └────────────────────────────┘
typ       └───────────────┘  └────────────────────────────┘      
2612    length_of_sublists_len h⟩,
id     └────────────────────┘ 
src    └────────────────────┘
typ    └────────────────────┘ 
2613  λ ⟨h₁, h₂⟩, h₂ ▸ mem_sublists_len_self h₁⟩
id     └┘  └┘       └───────────────────┘
src                  └───────────────────┘
typ    └┘  └┘       └───────────────────┘
2614  
2615  /- forall₂ -/
2616  
2617  section forall₂
2618  variables {r : α → β → Prop} {p : γ → δ → Prop}
2619  open relator
2620  
2621  run_cmd tactic.mk_iff_of_inductive_prop `list.forall₂ `list.forall₂_iff
id           └─────────────────────────────┘              
src          └─────────────────────────────┘              
typ          └─────────────────────────────┘              
doc          └─────────────────────────────┘
2622  
2623  @[simp] theorem forall₂_cons {R : α → β → Prop} {a b l₁ l₂} :
id                                        
typ                                       
doc    └──┘
2624    forall₂ R (a::l₁) (b::l₂) ↔ R a b ∧ forall₂ R l₁ l₂ :=
id     └─────┘   └┘└┘   └┘└┘       └─────┘  └┘ └┘
src    └─────┘     └┘      └┘            └─────┘
typ    └─────┘   └┘└┘   └┘└┘       └─────┘  └┘ └┘
2625  ⟨λ h, by cases h with h₁ h₂; split; assumption, λ ⟨h₁, h₂⟩, forall₂.cons h₁ h₂⟩
id                                                   └┘  └┘   └──────────┘
src           └────┘ └─────────┘  └───┘  └────────┘              └──────────┘
typ          └────┘└─────────┘  └───┘  └────────┘    └┘  └┘   └──────────┘
doc           └────┘ └─────────┘  └───┘  └────────┘
txt           └────┘ └─────────┘  └───┘  └────────┘
par           └────┘ └─────────┘  └───┘  └────────┘
pid                 └─────────┘
st           └────────────────────────────────────┘
2626  
2627  theorem forall₂.imp {R S : α → β → Prop}
id                                 
typ                                
2628    (H : ∀ a b, R a b → S a b) {l₁ l₂}
id                      
typ                     
2629    (h : forall₂ R l₁ l₂) : forall₂ S l₁ l₂ :=
id          └─────┘  └┘ └┘    └─────┘  └┘ └┘
src         └─────┘            └─────┘
typ         └─────┘  └┘ └┘    └─────┘  └┘ └┘
2630  by induction h; constructor; solve_by_elim
id                
src     └────────┘   └─────────┘  └─────────────
typ     └────────┘  └─────────┘  └─────────────
doc     └────────┘   └─────────┘  └─────────────
txt     └────────┘   └─────────┘  └─────────────
par     └────────┘   └─────────┘  └─────────────
pid                                           
st     └────────────────────────────────────────
2631  
src  
typ  
doc  
txt  
par  
pid  
st   
2632  lemma forall₂.mp {r q s : α → β → Prop} (h : ∀a b, r a b → q a b → s a b) :
id                                                              
typ                                                             
2633    ∀{l₁ l₂}, forall₂ r l₁ l₂ → forall₂ q l₁ l₂ → forall₂ s l₁ l₂
id      └┘ └┘   └─────┘  └┘ └┘   └─────┘  └┘ └┘   └─────┘  └┘ └┘
src              └─────┘           └─────┘           └─────┘
typ     └┘ └┘   └─────┘  └┘ └┘   └─────┘  └┘ └┘   └─────┘  └┘ └┘
2634  | []      []      forall₂.nil           forall₂.nil           := forall₂.nil
id     └┘      └┘                            └─────────┘              └─────────┘
src    └┘      └┘                            └─────────┘              └─────────┘
typ    └┘      └┘                            └─────────┘              └─────────┘
2635  | (a::l₁) (b::l₂) (forall₂.cons hr hrs) (forall₂.cons hq hqs) :=
id      └┘     └┘                  └┘ └─┘   └──────────┘ └┘ └─┘
src      └┘      └┘                           └──────────┘
typ     └┘     └┘                  └┘ └─┘   └──────────┘ └┘ └─┘
2636    forall₂.cons (h a b hr hq) (forall₂.mp hrs hqs)
id     └──────────┘               └────────┘
src    └──────────┘
typ    └──────────┘               └────────┘
2637  
2638  lemma forall₂.flip : ∀{a b}, forall₂ (flip r) b a → forall₂ r a b
id                             └─────┘  └──┘       └─────┘   
src                               └─────┘  └──┘          └─────┘
typ                            └─────┘  └──┘       └─────┘   
2639  | _ _                 forall₂.nil          := forall₂.nil
id                         └─────────┘             └─────────┘
src                        └─────────┘             └─────────┘
typ                        └─────────┘             └─────────┘
2640  | (a :: as) (b :: bs) (forall₂.cons h₁ h₂) := forall₂.cons h₁ h₂.flip
id        └┘        └┘      └──────────┘ └┘ └┘     └──────────┘
src       └┘        └┘      └──────────┘           └──────────┘
typ       └┘        └┘      └──────────┘ └┘ └┘     └──────────┘
2641  
2642  lemma forall₂_same {r : α → α → Prop} : ∀{l}, (∀x∈l, r x x) → forall₂ r l l
id                                                        └─────┘   
src                                                                └─────┘
typ                                                       └─────┘   
2643  | []      _ := forall₂.nil
id     └┘           └─────────┘
src    └┘           └─────────┘
typ    └┘           └─────────┘
2644  | (a::as) h := forall₂.cons
id       └┘        └──────────┘
src      └┘         └──────────┘
typ      └┘        └──────────┘
2645      (h _ (mem_cons_self _ _))
id             └───────────┘
src            └───────────┘
typ            └───────────┘
2646      (forall₂_same $ assume a ha, h a $ mem_cons_of_mem _ ha)
id        └──────────┘           └┘       └─────────────┘   └┘
src                                         └─────────────┘
typ       └──────────┘           └┘       └─────────────┘   └┘
2647  
2648  lemma forall₂_refl {r} [is_refl α r] (l : list α) : forall₂ r l l :=
id                           └─────┘         └──┘     └─────┘   
src                          └─────┘           └──┘      └─────┘
typ                          └─────┘         └──┘     └─────┘   
2649  forall₂_same $ assume a h, is_refl.refl _ _
id   └──────────┘             └──────────┘
src  └──────────┘               └──────────┘
typ  └──────────┘             └──────────┘
2650  
2651  lemma forall₂_eq_eq_eq : forall₂ ((=) : α → α → Prop) = (=) :=
id                            └─────┘                    
src                           └─────┘                      
typ                           └─────┘                    
2652  begin
st   └─────
2653    funext a b, apply propext,
id                       └─────┘
src    └────────┘  └────┘└─────┘
typ    └────────┘  └────┘└─────┘
doc    └────────┘  └────┘
txt    └────────┘  └────┘
par    └────────┘  └────┘
pid          └──┘       
st   ───────────┘└─────────────┘└─
2654    split,
src    └───┘
typ    └───┘
doc    └───┘
txt    └───┘
par    └───┘
st   ──────┘└─
2655    { assume h, induction h, {refl}, simp only [*]; split; refl },
id                           
src      └──────┘  └────────┘    └──┘   └───────────┘  └───┘  └───┘
typ      └──────┘  └────────┘   └──┘   └───────────┘  └───┘  └───┘
doc      └──────┘  └────────┘    └──┘   └───────────┘  └───┘  └───┘
txt      └──────┘  └────────┘    └──┘   └───────────┘  └───┘  └───┘
par      └──────┘  └────────┘    └──┘   └───────────┘  └───┘  └───┘
pid      └──────┘                          └──┘└──┘             
st   ───┘└──────┘└───────────┘└─────┘└┘└──────────────────────────┘└┘
2656    { assume h, subst h, exact forall₂_refl _ }
id                               └──────────┘
src      └──────┘  └────┘   └────┘└──────────┘└─┘
typ      └──────┘  └────┘  └────┘└──────────┘└─┘
doc      └──────┘  └────┘   └────┘            └─┘
txt      └──────┘  └────┘   └────┘            └─┘
par      └──────┘  └────┘   └────┘            └─┘
pid      └──────┘                           └┘
st   ───────────┘└───────┘└─────────────────────┘└─
2657  end
st   ──┘
2658  
2659  @[simp] lemma forall₂_nil_left_iff {l} : forall₂ r nil l ↔ l = nil :=
id                                            └─────┘  └─┘     └─┘
src                                           └─────┘   └─┘       └─┘
typ                                           └─────┘  └─┘     └─┘
doc    └──┘
2660  ⟨λ H, by cases H; refl, by rintro rfl; exact forall₂.nil⟩
id                                              └─────────┘
src           └────┘   └──┘     └────────┘  └────┘└─────────┘
typ          └────┘  └──┘     └────────┘  └────┘└─────────┘
doc           └────┘   └──┘     └────────┘  └────┘
txt           └────┘   └──┘     └────────┘  └────┘
par           └────┘   └──┘     └────────┘  └────┘
pid                                  └──┘       
st           └────────────┘    └────────────────────────────┘
2661  
2662  @[simp] lemma forall₂_nil_right_iff {l} : forall₂ r l nil ↔ l = nil :=
id                                             └─────┘   └─┘    └─┘
src                                            └─────┘     └─┘     └─┘
typ                                            └─────┘   └─┘    └─┘
doc    └──┘
2663  ⟨λ H, by cases H; refl, by rintro rfl; exact forall₂.nil⟩
id                                              └─────────┘
src           └────┘   └──┘     └────────┘  └────┘└─────────┘
typ          └────┘  └──┘     └────────┘  └────┘└─────────┘
doc           └────┘   └──┘     └────────┘  └────┘
txt           └────┘   └──┘     └────────┘  └────┘
par           └────┘   └──┘     └────────┘  └────┘
pid                                  └──┘       
st           └────────────┘    └────────────────────────────┘
2664  
2665  lemma forall₂_cons_left_iff {a l u} : forall₂ r (a::l) u ↔ (∃b u', r a b ∧ forall₂ r l u' ∧ u = b :: u') :=
id                                         └─────┘   └┘      └┘     └─────┘   └┘     └┘ └┘
src                                        └─────┘     └┘                   └─────┘              └┘
typ                                        └─────┘   └┘      └┘     └─────┘   └┘     └┘ └┘
2666  iff.intro
id   └───────┘
src  └───────┘
typ  └───────┘
2667    (assume h, match u, h with (b :: u'), forall₂.cons h₁ h₂ := ⟨b, u', h₁, h₂, rfl⟩ end)
id                               └┘ └┘   └──────────┘ └┘ └┘                    └─┘
src                                  └┘      └──────────┘                          └─┘
typ                              └┘ └┘   └──────────┘ └┘ └┘                    └─┘
2668    (assume h, match u, h with _, ⟨b, u', h₁, h₂, rfl⟩ := forall₂.cons h₁ h₂ end)
id                                        └┘  └┘  └─┘     └──────────┘
src                                                  └─┘     └──────────┘
typ                                       └┘  └┘  └─┘     └──────────┘
2669  
2670  lemma forall₂_cons_right_iff {b l u} :
2671    forall₂ r u (b::l) ↔ (∃a u', r a b ∧ forall₂ r u' l ∧ u = a :: u') :=
id     └─────┘    └┘     └┘     └─────┘  └┘      └┘ └┘
src    └─────┘       └┘                 └─────┘              └┘
typ    └─────┘    └┘     └┘     └─────┘  └┘      └┘ └┘
2672  iff.intro
id   └───────┘
src  └───────┘
typ  └───────┘
2673    (assume h, match u, h with (b :: u'), forall₂.cons h₁ h₂ := ⟨b, u', h₁, h₂, rfl⟩ end)
id                               └┘ └┘   └──────────┘ └┘ └┘                    └─┘
src                                  └┘      └──────────┘                          └─┘
typ                              └┘ └┘   └──────────┘ └┘ └┘                    └─┘
2674    (assume h, match u, h with _, ⟨b, u', h₁, h₂, rfl⟩ := forall₂.cons h₁ h₂ end)
id                                        └┘  └┘  └─┘     └──────────┘
src                                                  └─┘     └──────────┘
typ                                       └┘  └┘  └─┘     └──────────┘
2675  
2676  lemma forall₂_and_left {r : α → β → Prop} {p : α → Prop} :
id                                                
typ                                               
2677    ∀l u, forall₂ (λa b, p a ∧ r a b) l u ↔ (∀a∈l, p a) ∧ forall₂ r l u
id         └─────┘                         └─────┘   
src          └─────┘                                      └─────┘
typ        └─────┘                         └─────┘   
2678  | []     u := by simp only [forall₂_nil_left_iff, forall_prop_of_false (not_mem_nil _), imp_true_iff, true_and]
id     └┘                        └──────────────────┘  └──────────────────┘  └─────────┘     └──────────┘  └──────┘
src    └┘             └─────────┘└──────────────────┘└┘└──────────────────┘ └─────────┘└───┘└──────────┘└┘└──────┘└┘
typ    └┘             └─────────┘└──────────────────┘└┘└──────────────────┘ └─────────┘└───┘└──────────┘└┘└──────┘└┘
doc                   └─────────┘                    └┘                                └───┘            └┘        └┘
txt                   └─────────┘                    └┘                                └───┘            └┘        └┘
par                   └─────────┘                    └┘                                └───┘            └┘        └┘
pid                       └──┘└┘                    └┘                                └───┘            └┘        
st                   └──────────────────────────────────────────────────────────────────────────────────────────────┘
2679  | (a::l) u := by simp only [forall₂_and_left l, forall₂_cons_left_iff, forall_mem_cons,
id       └┘                      └──────────────┘   └───────────────────┘  └─────────────┘
src      └┘           └─────────┘                 └┘└───────────────────┘└┘└─────────────┘└─
typ      └┘           └─────────┘└──────────────┘└┘└───────────────────┘└┘└─────────────┘└─
doc                   └─────────┘                 └┘                     └┘               └─
txt                   └─────────┘                 └┘                     └┘               └─
par                   └─────────┘                 └┘                     └┘               └─
pid                       └──┘└┘                 └┘                     └┘               └─
st                   └───────────────────────────────────────────────────────────────────────
2680      and_assoc, and_comm, and.left_comm, exists_and_distrib_left.symm]
id       └───────┘  └──────┘  └───────────┘
src  ───┘└───────┘└┘└──────┘└┘└───────────┘└┘                            └─
typ  ───┘└───────┘└┘└──────┘└┘└───────────┘└┘└──────────────────────────┘└─
doc  ───┘         └┘        └┘             └┘                            └─
txt  ───┘         └┘        └┘             └┘                            └─
par  ───┘         └┘        └┘             └┘                            └─
pid  ───┘         └┘        └┘             └┘                            
st   ──────────────────────────────────────────────────────────────────────
2681  
src  
typ  
doc  
txt  
par  
pid  
st   
2682  @[simp] lemma forall₂_map_left_iff {f : γ → α} :
id                                              
typ                                             
doc    └──┘
2683    ∀{l u}, forall₂ r (map f l) u ↔ forall₂ (λc b, r (f c) b) l u
id          └─────┘   └─┘      └─────┘              
src            └─────┘    └─┘         └─────┘
typ         └─────┘   └─┘      └─────┘              
2684  | []     _ := by simp only [map, forall₂_nil_left_iff]
id     └┘                        └─┘  └──────────────────┘
src    └┘             └─────────┘└─┘└┘└──────────────────┘└┘
typ    └┘             └─────────┘└─┘└┘└──────────────────┘└┘
doc                   └─────────┘   └┘                    └┘
txt                   └─────────┘   └┘                    └┘
par                   └─────────┘   └┘                    └┘
pid                       └──┘└┘   └┘                    
st                   └─────────────────────────────────────┘
2685  | (a::l) _ := by simp only [map, forall₂_cons_left_iff, forall₂_map_left_iff]
id       └┘                      └─┘  └───────────────────┘
src      └┘           └─────────┘└─┘└┘└───────────────────┘└┘                    └─
typ      └┘           └─────────┘└─┘└┘└───────────────────┘└┘└──────────────────┘└─
doc                   └─────────┘   └┘                     └┘                    └─
txt                   └─────────┘   └┘                     └┘                    └─
par                   └─────────┘   └┘                     └┘                    └─
pid                       └──┘└┘   └┘                     └┘                    
st                   └─────────────────────────────────────────────────────────────
2686  
src  
typ  
doc  
txt  
par  
pid  
st   
2687  @[simp] lemma forall₂_map_right_iff {f : γ → β} :
id                                               
typ                                              
doc    └──┘
2688    ∀{l u}, forall₂ r l (map f u) ↔ forall₂ (λa c, r a (f c)) l u
id          └─────┘    └─┘     └─────┘              
src            └─────┘      └─┘       └─────┘
typ         └─────┘    └─┘     └─────┘              
2689  | _ []     := by simp only [map, forall₂_nil_right_iff]
id       └┘                      └─┘  └───────────────────┘
src      └┘           └─────────┘└─┘└┘└───────────────────┘└┘
typ      └┘           └─────────┘└─┘└┘└───────────────────┘└┘
doc                   └─────────┘   └┘                     └┘
txt                   └─────────┘   └┘                     └┘
par                   └─────────┘   └┘                     └┘
pid                       └──┘└┘   └┘                     
st                   └──────────────────────────────────────┘
2690  | _ (b::u) := by simp only [map, forall₂_cons_right_iff, forall₂_map_right_iff]
id         └┘                    └─┘  └────────────────────┘
src        └┘         └─────────┘└─┘└┘└────────────────────┘└┘                     └─
typ        └┘         └─────────┘└─┘└┘└────────────────────┘└┘└───────────────────┘└─
doc                   └─────────┘   └┘                      └┘                     └─
txt                   └─────────┘   └┘                      └┘                     └─
par                   └─────────┘   └┘                      └┘                     └─
pid                       └──┘└┘   └┘                      └┘                     
st                   └───────────────────────────────────────────────────────────────
2691  
src  
typ  
doc  
txt  
par  
pid  
st   
2692  lemma left_unique_forall₂ (hr : left_unique r) : left_unique (forall₂ r)
id                                   └─────────┘     └─────────┘  └─────┘ 
src                                  └─────────┘      └─────────┘  └─────┘
typ                                  └─────────┘     └─────────┘  └─────┘ 
2693  | a₀ nil a₁ forall₂.nil forall₂.nil := rfl
id        └─┘                └─────────┘    └─┘
src       └─┘                └─────────┘    └─┘
typ       └─┘                └─────────┘    └─┘
2694  | (a₀::l₀) (b::l) (a₁::l₁) (forall₂.cons ha₀ h₀) (forall₂.cons ha₁ h₁) :=
id        └┘      └┘      └┘                  └─┘ └┘   └──────────┘ └─┘ └┘
src       └┘      └┘      └┘                           └──────────┘
typ       └┘      └┘      └┘                  └─┘ └┘   └──────────┘ └─┘ └┘
2695    hr ha₀ ha₁ ▸ left_unique_forall₂ h₀ h₁ ▸ rfl
id     └┘          └─────────────────┘        └─┘
src                                           └─┘
typ    └┘          └─────────────────┘        └─┘
2696  
2697  lemma right_unique_forall₂ (hr : right_unique r) : right_unique (forall₂ r)
id                                    └──────────┘     └──────────┘  └─────┘ 
src                                   └──────────┘      └──────────┘  └─────┘
typ                                   └──────────┘     └──────────┘  └─────┘ 
2698  | nil a₀ a₁ forall₂.nil forall₂.nil := rfl
id     └─┘                   └─────────┘    └─┘
src    └─┘                   └─────────┘    └─┘
typ    └─┘                   └─────────┘    └─┘
2699  | (b::l) (a₀::l₀) (a₁::l₁) (forall₂.cons ha₀ h₀) (forall₂.cons ha₁ h₁) :=
id       └┘      └┘       └┘                  └─┘ └┘   └──────────┘ └─┘ └┘
src      └┘      └┘       └┘                           └──────────┘
typ      └┘      └┘       └┘                  └─┘ └┘   └──────────┘ └─┘ └┘
2700    hr ha₀ ha₁ ▸ right_unique_forall₂ h₀ h₁ ▸ rfl
id     └┘          └──────────────────┘        └─┘
src                                            └─┘
typ    └┘          └──────────────────┘        └─┘
2701  
2702  lemma bi_unique_forall₂ (hr : bi_unique r) : bi_unique (forall₂ r) :=
id                                 └───────┘     └───────┘  └─────┘ 
src                                └───────┘      └───────┘  └─────┘
typ                                └───────┘     └───────┘  └─────┘ 
2703  ⟨assume a b c, left_unique_forall₂ hr.1, assume a b c, right_unique_forall₂ hr.2⟩
id               └─────────────────┘ └┘              └──────────────────┘ └┘
src                 └─────────────────┘                    └──────────────────┘   
typ              └─────────────────┘ └┘              └──────────────────┘ └┘
2704  
2705  theorem forall₂_length_eq {R : α → β → Prop} :
id                                     
typ                                    
2706    ∀ {l₁ l₂}, forall₂ R l₁ l₂ → length l₁ = length l₂
id       └┘ └┘   └─────┘  └┘ └┘   └────┘ └┘  └────┘ └┘
src               └─────┘           └────┘     └────┘
typ      └┘ └┘   └─────┘  └┘ └┘   └────┘ └┘  └────┘ └┘
2707  | _ _ forall₂.nil          := rfl
id         └─────────┘             └─┘
src        └─────────┘             └─┘
typ        └─────────┘             └─┘
2708  | _ _ (forall₂.cons h₁ h₂) := congr_arg succ (forall₂_length_eq h₂)
id          └──────────┘    └┘     └───────┘ └──┘  └───────────────┘
src         └──────────┘           └───────┘ └──┘
typ         └──────────┘    └┘     └───────┘ └──┘  └───────────────┘
2709  
2710  theorem forall₂_zip {R : α → β → Prop} :
id                               
typ                              
2711    ∀ {l₁ l₂}, forall₂ R l₁ l₂ → ∀ {a b}, (a, b) ∈ zip l₁ l₂ → R a b
id       └┘ └┘   └─────┘  └┘ └┘               └─┘ └┘ └┘     
src               └─────┘                           └─┘
typ      └┘ └┘   └─────┘  └┘ └┘               └─┘ └┘ └┘     
2712  | _ _ (forall₂.cons h₁ h₂) x y (or.inl rfl) := h₁
id          └──────────┘ └┘          └────┘ └─┘
src         └──────────┘             └────┘ └─┘
typ         └──────────┘ └┘          └────┘ └─┘
2713  | _ _ (forall₂.cons h₁ h₂) x y (or.inr h₃) := forall₂_zip h₂ h₃
id          └──────────┘    └┘       └────┘ └┘     └─────────┘
src         └──────────┘             └────┘
typ         └──────────┘    └┘       └────┘ └┘     └─────────┘
2714  
2715  theorem forall₂_iff_zip {R : α → β → Prop} {l₁ l₂} : forall₂ R l₁ l₂ ↔
id                                                      └─────┘  └┘ └┘ 
src                                                       └─────┘         
typ                                                     └─────┘  └┘ └┘ 
2716    length l₁ = length l₂ ∧ ∀ {a b}, (a, b) ∈ zip l₁ l₂ → R a b :=
id     └────┘ └┘  └────┘ └┘              └─┘ └┘ └┘     
src    └────┘     └────┘                     └─┘
typ    └────┘ └┘  └────┘ └┘              └─┘ └┘ └┘     
2717  ⟨λ h, ⟨forall₂_length_eq h, @forall₂_zip _ _ _ _ _ h⟩,
id         └───────────────┘    └─────────┘           
src         └───────────────┘     └─────────┘
typ        └───────────────┘    └─────────┘           
2718   λ h, begin
id      
typ     
st         └─────
2719    cases h with h₁ h₂,
id           
src    └────┘ └─────────┘
typ    └────┘└─────────┘
doc    └────┘ └─────────┘
txt    └────┘ └─────────┘
par    └────┘ └─────────┘
pid          └─────────┘
st   ───────────────────┘└─
2720    induction l₁ with a l₁ IH generalizing l₂,
id               └┘
src    └────────┘  └───────────────────────────┘
typ    └────────┘└┘└───────────────────────────┘
doc    └────────┘  └───────────────────────────┘
txt    └────────┘  └───────────────────────────┘
par    └────────┘  └───────────────────────────┘
pid               └──────────┘└──────────────┘
st   ──────────────────────────────────────────┘└─
2721    { cases length_eq_zero.1 h₁.symm, constructor },
id             └────────────┘   └─────┘
src      └────┘└────────────┘└─┘└─────┘  └──────────┘
typ      └────┘└────────────┘└─┘└─────┘  └──────────┘
doc      └────┘              └─┘         └──────────┘
txt      └────┘              └─┘         └──────────┘
par      └────┘              └─┘         └──────────┘
pid                         └─┘                    
st   ───┘└────────────────────────────┘└────────────┘└┘
2722    { cases l₂ with b l₂; injection h₁ with h₁,
id             └┘                      └┘
src      └────┘  └────────┘  └────────┘  └──────┘
typ      └────┘└┘└────────┘  └────────┘└┘└──────┘
doc      └────┘  └────────┘  └────────┘  └──────┘
txt      └────┘  └────────┘  └────────┘  └──────┘
par      └────┘  └────────┘  └────────┘  └──────┘
pid             └────────┘             └──────┘
st   ───────────────────────────────────────────┘└─
2723      exact forall₂.cons (h₂ $ or.inl rfl) (IH h₁ $ λ a b h, h₂ $ or.inr h) }
id             └──────────┘       └────┘ └─┘   └┘ └┘            └┘   └────┘
src      └────┘└──────────┘    └────┘└─┘└┘       └──────┘   └────┘ └┘
typ      └────┘└──────────┘    └────┘└─┘└┘ └┘└┘  └──────┘└┘ └────┘ └┘
doc      └────┘                         └┘       └──────┘          └┘
txt      └────┘                         └┘       └──────┘          └┘
par      └────┘                         └┘       └──────┘          └┘
pid                                    └┘       └──────┘          
st   ─────────────────────────────────────────────────────────────────────────┘└─
2724  end⟩
st   ──┘
2725  
2726  theorem forall₂_take {R : α → β → Prop} :
id                                
typ                               
2727    ∀ n {l₁ l₂}, forall₂ R l₁ l₂ → forall₂ R (take n l₁) (take n l₂)
id         └┘ └┘   └─────┘  └┘ └┘   └─────┘   └──┘  └┘   └──┘  └┘
src                 └─────┘           └─────┘    └──┘        └──┘
typ        └┘ └┘   └─────┘  └┘ └┘   └─────┘   └──┘  └┘   └──┘  └┘
2728  | 0 _ _ _ := by simp only [forall₂.nil, take]
id                              └─────────┘  └──┘
src                  └─────────┘└─────────┘└┘└──┘└┘
typ                  └─────────┘└─────────┘└┘└──┘└┘
doc                  └─────────┘           └┘    └┘
txt                  └─────────┘           └┘    └┘
par                  └─────────┘           └┘    └┘
pid                      └──┘└┘           └┘    
st                  └─────────────────────────────┘
2729  | (n+1) _ _ (forall₂.nil) := by simp only [forall₂.nil, take]
id               └─────────┘                   └─────────┘  └──┘
src              └─────────┘        └─────────┘└─────────┘└┘└──┘└┘
typ              └─────────┘        └─────────┘└─────────┘└┘└──┘└┘
doc                                  └─────────┘           └┘    └┘
txt                                  └─────────┘           └┘    └┘
par                                  └─────────┘           └┘    └┘
pid                                      └──┘└┘           └┘    
st                                  └─────────────────────────────┘
2730  | (n+1) _ _ (forall₂.cons h₁ h₂) := by simp [and.intro h₁ h₂, forall₂_take n]
id               └──────────┘                    └───────┘ └┘ └┘  └──────────┘ 
src              └──────────┘              └────┘└───────┘    └┘             └─
typ              └──────────┘              └────┘└───────┘└┘└┘└┘└──────────┘└─
doc                                         └────┘             └┘             └─
txt                                         └────┘             └┘             └─
par                                         └────┘             └┘             └─
pid                                                          └┘             
st                                         └───────────────────────────────────────
2731  
src  
typ  
doc  
txt  
par  
pid  
st   
2732  theorem forall₂_drop {R : α → β → Prop} :
id                                
typ                               
2733    ∀ n {l₁ l₂}, forall₂ R l₁ l₂ → forall₂ R (drop n l₁) (drop n l₂)
id         └┘ └┘   └─────┘  └┘ └┘   └─────┘   └──┘  └┘   └──┘  └┘
src                 └─────┘           └─────┘    └──┘        └──┘
typ        └┘ └┘   └─────┘  └┘ └┘   └─────┘   └──┘  └┘   └──┘  └┘
2734  | 0 _ _ h := by simp only [drop, h]
id                              └──┘  
src                  └─────────┘└──┘└┘ └┘
typ                  └─────────┘└──┘└┘└┘
doc                  └─────────┘    └┘ └┘
txt                  └─────────┘    └┘ └┘
par                  └─────────┘    └┘ └┘
pid                      └──┘└┘    └┘ 
st                  └───────────────────┘
2735  | (n+1) _ _ (forall₂.nil) := by simp only [forall₂.nil, drop]
id               └─────────┘                   └─────────┘  └──┘
src              └─────────┘        └─────────┘└─────────┘└┘└──┘└┘
typ              └─────────┘        └─────────┘└─────────┘└┘└──┘└┘
doc                                  └─────────┘           └┘    └┘
txt                                  └─────────┘           └┘    └┘
par                                  └─────────┘           └┘    └┘
pid                                      └──┘└┘           └┘    
st                                  └─────────────────────────────┘
2736  | (n+1) _ _ (forall₂.cons h₁ h₂) := by simp [and.intro h₁ h₂, forall₂_drop n]
id               └──────────┘                    └───────┘ └┘ └┘  └──────────┘ 
src              └──────────┘              └────┘└───────┘    └┘             └─
typ              └──────────┘              └────┘└───────┘└┘└┘└┘└──────────┘└─
doc                                         └────┘             └┘             └─
txt                                         └────┘             └┘             └─
par                                         └────┘             └┘             └─
pid                                                          └┘             
st                                         └───────────────────────────────────────
2737  
src  
typ  
doc  
txt  
par  
pid  
st   
2738  theorem forall₂_take_append {R : α → β → Prop} (l : list α) (l₁ : list β) (l₂ : list β)
id                                                     └──┘         └──┘         └──┘ 
src                                                      └──┘          └──┘          └──┘
typ                                                    └──┘         └──┘         └──┘ 
2739    (h : forall₂ R l (l₁ ++ l₂)) : forall₂ R (list.take (length l₁) l) l₁ :=
id          └─────┘    └┘ └┘ └┘     └─────┘   └───────┘  └────┘ └┘    └┘
src         └─────┘         └┘        └─────┘    └───────┘  └────┘
typ         └─────┘    └┘ └┘ └┘     └─────┘   └───────┘  └────┘ └┘    └┘
2740  have h': forall₂ R (take (length l₁) l) (take (length l₁) (l₁ ++ l₂)), from forall₂_take (length l₁) h,
id            └─────┘   └──┘  └────┘ └┘     └──┘  └────┘ └┘   └┘ └┘ └┘         └──────────┘  └────┘ └┘  
src           └─────┘    └──┘  └────┘         └──┘  └────┘         └┘            └──────────┘  └────┘
typ           └─────┘   └──┘  └────┘ └┘     └──┘  └────┘ └┘   └┘ └┘ └┘         └──────────┘  └────┘ └┘  
2741  by rwa [take_left] at h'
id           └───────┘
src     └───┘└───────┘└───────
typ     └───┘└───────┘└───────
doc     └───┘         └───────
txt     └───┘         └───────
par     └───┘         └───────
pid        └┘         └────┘
st     └─────────────┘└──────
2742  
src  
typ  
doc  
txt  
par  
pid  
st   
2743  theorem forall₂_drop_append {R : α → β → Prop} (l : list α) (l₁ : list β) (l₂ : list β)
id                                                     └──┘         └──┘         └──┘ 
src                                                      └──┘          └──┘          └──┘
typ                                                    └──┘         └──┘         └──┘ 
2744    (h : forall₂ R l (l₁ ++ l₂)) : forall₂ R (list.drop (length l₁) l) l₂ :=
id          └─────┘    └┘ └┘ └┘     └─────┘   └───────┘  └────┘ └┘    └┘
src         └─────┘         └┘        └─────┘    └───────┘  └────┘
typ         └─────┘    └┘ └┘ └┘     └─────┘   └───────┘  └────┘ └┘    └┘
2745  have h': forall₂ R (drop (length l₁) l) (drop (length l₁) (l₁ ++ l₂)), from forall₂_drop (length l₁) h,
id            └─────┘   └──┘  └────┘ └┘     └──┘  └────┘ └┘   └┘ └┘ └┘         └──────────┘  └────┘ └┘  
src           └─────┘    └──┘  └────┘         └──┘  └────┘         └┘            └──────────┘  └────┘
typ           └─────┘   └──┘  └────┘ └┘     └──┘  └────┘ └┘   └┘ └┘ └┘         └──────────┘  └────┘ └┘  
2746  by rwa [drop_left] at h'
id           └───────┘
src     └───┘└───────┘└───────
typ     └───┘└───────┘└───────
doc     └───┘         └───────
txt     └───┘         └───────
par     └───┘         └───────
pid        └┘         └────┘
st     └─────────────┘└──────
2747  
src  
typ  
doc  
txt  
par  
pid  
st   
2748  lemma rel_mem (hr : bi_unique r) : (r ⇒ forall₂ r ⇒ iff) (∈) (∈)
id                       └───────┘        └─────┘   └─┘     
src                      └───────┘          └─────┘    └─┘     
typ                      └───────┘        └─────┘   └─┘     
2749  | a b h [] [] forall₂.nil := by simp only [not_mem_nil]
id           └┘ └┘ └─────────┘                  └─────────┘
src          └┘ └┘ └─────────┘       └─────────┘└─────────┘└┘
typ          └┘ └┘ └─────────┘       └─────────┘└─────────┘└┘
doc                                  └─────────┘           └┘
txt                                  └─────────┘           └┘
par                                  └─────────┘           └┘
pid                                      └──┘└┘           
st                                  └───────────────────────┘
2750  | a b h (a'::as) (b'::bs) (forall₂.cons h₁ h₂) := rel_or (rel_eq hr h h₁) (rel_mem h h₂)
id             └┘       └┘     └──────────┘ └┘ └┘     └────┘  └────┘ └┘        └─────┘
src             └┘       └┘     └──────────┘           └────┘  └────┘
typ            └┘       └┘     └──────────┘ └┘ └┘     └────┘  └────┘ └┘        └─────┘
2751  
2752  lemma rel_map : ((r ⇒ p) ⇒ forall₂ r ⇒ forall₂ p) map map
id                          └─────┘   └─────┘   └─┘ └─┘
src                           └─────┘    └─────┘    └─┘ └─┘
typ                         └─────┘   └─────┘   └─┘ └─┘
2753  | f g h [] [] forall₂.nil := forall₂.nil
id           └┘ └┘ └─────────┘    └─────────┘
src          └┘ └┘ └─────────┘    └─────────┘
typ          └┘ └┘ └─────────┘    └─────────┘
2754  | f g h (a::as) (b::bs) (forall₂.cons h₁ h₂) := forall₂.cons (h h₁) (rel_map @h h₂)
id            └┘      └┘     └──────────┘ └┘ └┘     └──────────┘         └─────┘
src            └┘      └┘     └──────────┘           └──────────┘
typ           └┘      └┘     └──────────┘ └┘ └┘     └──────────┘         └─────┘
2755  
2756  lemma rel_append : (forall₂ r ⇒ forall₂ r ⇒ forall₂ r) append append
id                       └─────┘   └─────┘   └─────┘   └────┘ └────┘
src                      └─────┘    └─────┘    └─────┘    └────┘ └────┘
typ                      └─────┘   └─────┘   └─────┘   └────┘ └────┘
2757  | [] [] h l₁ l₂ hl := hl
id     └┘ └┘         └┘
src    └┘ └┘
typ    └┘ └┘         └┘
2758  | (a::as) (b::bs) (forall₂.cons h₁ h₂) l₁ l₂ hl := forall₂.cons h₁ (rel_append h₂ hl)
id       └┘      └┘     └──────────┘ └┘ └┘        └┘    └──────────┘     └────────┘
src      └┘      └┘     └──────────┘                    └──────────┘
typ      └┘      └┘     └──────────┘ └┘ └┘        └┘    └──────────┘     └────────┘
2759  
2760  lemma rel_join : (forall₂ (forall₂ r) ⇒ forall₂ r) join join
id                     └─────┘  └─────┘    └─────┘   └──┘ └──┘
src                    └─────┘  └─────┘     └─────┘    └──┘ └──┘
typ                    └─────┘  └─────┘    └─────┘   └──┘ └──┘
2761  | [] [] forall₂.nil := forall₂.nil
id     └┘ └┘ └─────────┘    └─────────┘
src    └┘ └┘ └─────────┘    └─────────┘
typ    └┘ └┘ └─────────┘    └─────────┘
2762  | (a::as) (b::bs) (forall₂.cons h₁ h₂) := rel_append h₁ (rel_join h₂)
id       └┘      └┘     └──────────┘ └┘ └┘     └────────┘     └──────┘
src      └┘      └┘     └──────────┘           └────────┘
typ      └┘      └┘     └──────────┘ └┘ └┘     └────────┘     └──────┘
2763  
2764  lemma rel_bind : (forall₂ r ⇒ (r ⇒ forall₂ p) ⇒ forall₂ p) list.bind list.bind :=
id                     └─────┘      └─────┘    └─────┘   └───────┘ └───────┘
src                    └─────┘        └─────┘     └─────┘    └───────┘ └───────┘
typ                    └─────┘      └─────┘    └─────┘   └───────┘ └───────┘
2765  assume a b h₁ f g h₂, rel_join (rel_map @h₂ h₁)
id            └┘   └┘  └──────┘  └─────┘  └┘ └┘
src                        └──────┘  └─────┘
typ           └┘   └┘  └──────┘  └─────┘  └┘ └┘
2766  
2767  lemma rel_foldl : ((p ⇒ r ⇒ p) ⇒ p ⇒ forall₂ r ⇒ p) foldl foldl
id                                └─────┘     └───┘ └───┘
src                                   └─────┘       └───┘ └───┘
typ                               └─────┘     └───┘ └───┘
2768  | f g hfg _ _ h _ _ forall₂.nil := h
id                      └─────────┘
src                      └─────────┘
typ                     └─────────┘
2769  | f g hfg x y hxy _ _ (forall₂.cons hab hs) := rel_foldl @hfg (hfg hxy hab) hs
id         └─┘     └─┘      └──────────┘ └─┘ └┘     └───────┘  └─┘
src                         └──────────┘
typ        └─┘     └─┘      └──────────┘ └─┘ └┘     └───────┘  └─┘
2770  
2771  lemma rel_foldr : ((r ⇒ p ⇒ p) ⇒ p ⇒ forall₂ r ⇒ p) foldr foldr
id                                └─────┘     └───┘ └───┘
src                                   └─────┘       └───┘ └───┘
typ                               └─────┘     └───┘ └───┘
2772  | f g hfg _ _ h _ _ forall₂.nil := h
id                      └─────────┘
src                      └─────────┘
typ                     └─────────┘
2773  | f g hfg x y hxy _ _ (forall₂.cons hab hs) := hfg hab (rel_foldr @hfg hxy hs)
id         └─┘     └─┘      └──────────┘ └─┘ └┘              └───────┘
src                         └──────────┘
typ        └─┘     └─┘      └──────────┘ └─┘ └┘              └───────┘
2774  
2775  lemma rel_filter {p : α → Prop} {q : β → Prop} [decidable_pred p] [decidable_pred q]
id                                                 └────────────┘    └────────────┘ 
src                                                  └────────────┘     └────────────┘
typ                                                └────────────┘    └────────────┘ 
2776    (hpq : (r ⇒ (↔)) p q) :
id                    
src               
typ                   
2777    (forall₂ r ⇒ forall₂ r) (filter p) (filter q)
id      └─────┘   └─────┘    └────┘    └────┘ 
src     └─────┘    └─────┘     └────┘     └────┘
typ     └─────┘   └─────┘    └────┘    └────┘ 
2778  | _ _ forall₂.nil := forall₂.nil
id         └─────────┘    └─────────┘
src        └─────────┘    └─────────┘
typ        └─────────┘    └─────────┘
2779  | (a::as) (b::bs) (forall₂.cons h₁ h₂) :=
id       └┘      └┘     └──────────┘
src      └┘      └┘     └──────────┘
typ      └┘      └┘     └──────────┘
2780    begin
st     └─────
2781      by_cases p a,
id                 
src      └───────┘ 
typ      └───────┘
doc      └───────┘ 
txt      └───────┘ 
par      └───────┘ 
pid               
st   ───────────────┘└─
2782      { have : q b, { rwa [← hpq h₁] },
id                            └─┘ └┘
src        └─────┘      └─────┘     └┘
typ        └─────┘    └─────┘└─┘└┘└┘
doc        └─────┘      └─────┘     └┘
txt        └─────┘      └─────┘     └┘
par        └─────┘      └─────┘     └┘
pid        └───┘└┘         └──┘     
st   ─────┘└────────┘└──┘└───────────┘└┘
2783        simp only [filter_cons_of_pos _ h, filter_cons_of_pos _ this, forall₂_cons, h₁, rel_filter h₂, and_true], },
id                    └────────────────┘     └────────────────┘   └──┘  └──────────┘  └┘  └────────┘ └┘  └──────┘
src        └─────────┘└────────────────┘└─┘ └┘└────────────────┘└─┘    └┘└──────────┘└┘  └┘            └┘└──────┘
typ        └─────────┘└────────────────┘└─┘└┘└────────────────┘└─┘└──┘└┘└──────────┘└┘└┘└┘└────────┘└┘└┘└──────┘
doc        └─────────┘                  └─┘ └┘                  └─┘    └┘            └┘  └┘            └┘        
txt        └─────────┘                  └─┘ └┘                  └─┘    └┘            └┘  └┘            └┘        
par        └─────────┘                  └─┘ └┘                  └─┘    └┘            └┘  └┘            └┘        
pid            └──┘└┘                  └─┘ └┘                  └─┘    └┘            └┘  └┘            └┘        
st   ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┘└──┘
2784      { have : ¬ q b, { rwa [← hpq h₁] },
id                              └─┘ └┘
src        └─────┘       └─────┘     └┘
typ        └─────┘     └─────┘└─┘└┘└┘
doc        └─────┘       └─────┘     └┘
txt        └─────┘       └─────┘     └┘
par        └─────┘       └─────┘     └┘
pid        └───┘└┘          └──┘     
st   ─────────────────┘└──┘└───────────┘└┘
2785        simp only [filter_cons_of_neg _ h, filter_cons_of_neg _ this, rel_filter h₂], },
id                    └────────────────┘     └────────────────┘   └──┘  └────────┘ └┘
src        └─────────┘└────────────────┘└─┘ └┘└────────────────┘└─┘    └┘            
typ        └─────────┘└────────────────┘└─┘└┘└────────────────┘└─┘└──┘└┘└────────┘└┘
doc        └─────────┘                  └─┘ └┘                  └─┘    └┘            
txt        └─────────┘                  └─┘ └┘                  └─┘    └┘            
par        └─────────┘                  └─┘ └┘                  └─┘    └┘            
pid            └──┘└┘                  └─┘ └┘                  └─┘    └┘            
st   ─────────────────────────────────────────────────────────────────────────────────┘└────
2786    end
st   ────┘
2787  
2788  theorem filter_map_cons (f : α → option β) (a : α) (l : list α) :
id                                   └────┘               └──┘ 
src                                   └────┘                 └──┘
typ                                  └────┘               └──┘ 
2789    filter_map f (a :: l) = option.cases_on (f a) (filter_map f l) (λb, b :: filter_map f l) :=
id     └────────┘    └┘    └─────────────┘      └────────┘         └┘ └────────┘  
src    └────────┘      └┘     └─────────────┘        └────────┘             └┘ └────────┘
typ    └────────┘    └┘    └─────────────┘      └────────┘         └┘ └────────┘  
2790  begin
st   └─────
2791    generalize eq : f a = b,
id                      
src    └──────────────┘   
typ    └──────────────┘ 
doc    └──────────────┘   
txt    └──────────────┘   
par    └──────────────┘   
pid              └─┘└┘   
st   ────────────────────────┘└─
2792    cases b,
id           
src    └────┘
typ    └────┘
doc    └────┘
txt    └────┘
par    └────┘
pid         
st   ────────┘└─
2793    { rw filter_map_cons_none _ _ eq },
id          └──────────────────┘     └┘
src      └─┘└──────────────────┘└───┘└┘
typ      └─┘└──────────────────┘└───┘└┘
doc      └─┘                    └───┘  
txt      └─┘                    └───┘  
par      └─┘                    └───┘  
pid                            └───┘  
st   ───┘└─────────────────────────────┘└┘
2794    { rw filter_map_cons_some _ _ _ eq },
id          └──────────────────┘       └┘
src      └─┘└──────────────────┘└─────┘└┘
typ      └─┘└──────────────────┘└─────┘└┘
doc      └─┘                    └─────┘  
txt      └─┘                    └─────┘  
par      └─┘                    └─────┘  
pid                            └─────┘  
st   ────────────────────────────────────┘└──
2795  end
st   ──┘
2796  
2797  lemma rel_filter_map : ((r ⇒ option.rel p) ⇒ forall₂ r ⇒ forall₂ p) filter_map filter_map
id                              └────────┘    └─────┘   └─────┘   └────────┘ └────────┘
src                              └────────┘     └─────┘    └─────┘    └────────┘ └────────┘
typ                             └────────┘    └─────┘   └─────┘   └────────┘ └────────┘
2798  | f g hfg _ _ forall₂.nil := forall₂.nil
id                 └─────────┘    └─────────┘
src                └─────────┘    └─────────┘
typ                └─────────┘    └─────────┘
2799  | f g hfg (a::as) (b::bs) (forall₂.cons h₁ h₂) :=
id               └┘      └┘     └──────────┘
src              └┘      └┘     └──────────┘
typ              └┘      └┘     └──────────┘
2800    by rw [filter_map_cons, filter_map_cons];
id            └─────────────┘  └─────────────┘
src       └──┘└─────────────┘└┘└─────────────┘
typ       └──┘└─────────────┘└┘└─────────────┘
doc       └──┘               └┘               
txt       └──┘               └┘               
par       └──┘               └┘               
pid         └┘               └┘               
st       └──────────────────┘└───────────────┘└─
2801    from match f a, g b, hfg h₁ with
id                      └─┘ └┘
src    └───┘       └┘  └┘     └─────
typ    └───┘     └┘└┘└─┘└┘└─────
doc    └───┘       └┘  └┘     └─────
txt    └───┘       └┘  └┘     └─────
par    └───┘       └┘  └┘     └─────
pid    └───┘       └┘  └┘     └─────
st   ───────────────────────────────────
2802    | _, _, option.rel.none := rel_filter_map @hfg h₂
id             └─────────────┘                    └─┘
src  ─────────┘└─────────────┘└──┘                    
typ  ─────────┘└─────────────┘└──┘               └─┘  
doc  ─────────┘               └──┘                    
txt  ─────────┘               └──┘                    
par  ─────────┘               └──┘                    
pid  ─────────┘               └──┘                    
st   ────────────────────────────────────────────────────
2803    | _, _, option.rel.some h := forall₂.cons h (rel_filter_map @hfg h₂)
id             └─────────────┘     └──────────┘    └────────────┘      └┘
src  ─────────┘└─────────────┘ └──┘└──────────┘                      └─
typ  ─────────┘└─────────────┘└──┘└──────────┘  └────────────┘    └┘└─
doc  ─────────┘                └──┘                                  └─
txt  ─────────┘                └──┘                                  └─
par  ─────────┘                └──┘                                  └─
pid  ─────────┘                └──┘                                  └─
st   ───────────────────────────────────────────────────────────────────────
2804    end
src  ──────
typ  ──────
doc  ──────
txt  ──────
par  ──────
pid  ────┘
st   ──────
2805  
src  
typ  
doc  
txt  
par  
pid  
st   
2806  @[to_additive]
doc    └─────────┘
2807  lemma rel_prod [monoid α] [monoid β]
id                   └────┘    └────┘ 
src                  └────┘     └────┘
typ                  └────┘    └────┘ 
2808    (h : r 1 1) (hf : (r ⇒ r ⇒ r) (*) (*)) : (forall₂ r ⇒ r) prod prod :=
id                                       └─────┘     └──┘ └──┘
src                                          └─────┘       └──┘ └──┘
typ                                      └─────┘     └──┘ └──┘
doc                                                             └──┘ └──┘
2809  rel_foldl hf h
id   └───────┘ └┘ 
src  └───────┘
typ  └───────┘ └┘ 
2810  
2811  end forall₂
2812  
2813  /- sections -/
2814  
2815  theorem mem_sections {L : list (list α)} {f} : f ∈ sections L ↔ forall₂ (∈) f L :=
id                             └──┘  └──┘            └──────┘   └─────┘     
src                            └──┘  └──┘              └──────┘    └─────┘ 
typ                            └──┘  └──┘            └──────┘   └─────┘     
doc                                                     └──────┘
2816  begin
st   └─────
2817    refine ⟨λ h, _, λ h, _⟩,
src    └─────┘  └─────┘ └────┘
typ    └─────┘  └─────┘ └────┘
doc    └─────┘  └─────┘ └────┘
txt    └─────┘  └─────┘ └────┘
par    └─────┘  └─────┘ └────┘
pid            └─────┘ └────┘
st   ────────────────────────┘└─
2818    { induction L generalizing f, {cases mem_singleton.1 h, exact forall₂.nil},
id                                         └───────────┘           └─────────┘
src      └────────┘ └─────────────┘   └────┘└───────────┘└─┘   └────┘└─────────┘
typ      └────────┘└─────────────┘   └────┘└───────────┘└─┘  └────┘└─────────┘
doc      └────────┘ └─────────────┘   └────┘             └─┘   └────┘
txt      └────────┘ └─────────────┘   └────┘             └─┘   └────┘
par      └────────┘ └─────────────┘   └────┘             └─┘   └────┘
pid                └────────────┘                     └─┘        
st   ───┘└────────────────────────┘└────────────────────────┘└─────────────────┘└┘
2819      simp only [sections, bind_eq_bind, mem_bind, mem_map] at h,
id                  └──────┘  └──────────┘  └──────┘  └─────┘
src      └─────────┘└──────┘└┘└──────────┘└┘└──────┘└┘└─────┘└────┘
typ      └─────────┘└──────┘└┘└──────────┘└┘└──────┘└┘└─────┘└────┘
doc      └─────────┘└──────┘└┘            └┘        └┘       └────┘
txt      └─────────┘        └┘            └┘        └┘       └────┘
par      └─────────┘        └┘            └┘        └┘       └────┘
pid          └──┘└┘        └┘            └┘        └┘       └──┘
st   ─────────────────────────────────────────────────────────────┘└─
2820      rcases h with ⟨_, _, _, _, rfl⟩,
id              
src      └─────┘ └─────────────────────┘
typ      └─────┘└─────────────────────┘
doc      └─────┘ └─────────────────────┘
txt      └─────┘ └─────────────────────┘
par      └─────┘ └─────────────────────┘
pid             └─────────────────────┘
st   ──────────────────────────────────┘└─
2821      simp only [*, forall₂_cons, true_and] },
id                     └──────────┘  └──────┘
src      └────────────┘└──────────┘└┘└──────┘└┘
typ      └────────────┘└──────────┘└┘└──────┘└┘
doc      └────────────┘            └┘        └┘
txt      └────────────┘            └┘        └┘
par      └────────────┘            └┘        └┘
pid          └──┘└───┘            └┘        
st   ─────────────────────────────────────────┘└┘
2822    { induction h with a l f L al fL fs, {exact or.inl rfl},
id                                                └────┘ └─┘
src      └────────┘ └────────────────────┘   └────┘└────┘└─┘
typ      └────────┘└────────────────────┘   └────┘└────┘└─┘
doc      └────────┘ └────────────────────┘   └────┘      
txt      └────────┘ └────────────────────┘   └────┘      
par      └────────┘ └────────────────────┘   └────┘      
pid                └───────────────────┘              
st   ────────────────────────────────────┘└─────────────────┘└┘
2823      simp only [sections, bind_eq_bind, mem_bind, mem_map],
id                  └──────┘  └──────────┘  └──────┘  └─────┘
src      └─────────┘└──────┘└┘└──────────┘└┘└──────┘└┘└─────┘
typ      └─────────┘└──────┘└┘└──────────┘└┘└──────┘└┘└─────┘
doc      └─────────┘└──────┘└┘            └┘        └┘       
txt      └─────────┘        └┘            └┘        └┘       
par      └─────────┘        └┘            └┘        └┘       
pid          └──┘└┘        └┘            └┘        └┘       
st   ────────────────────────────────────────────────────────┘└─
2824      exact ⟨_, fs, _, al, rfl, rfl⟩ }
id                 └┘     └┘       └─┘
src      └────┘ └─┘  └───┘  └┘   └┘└─┘└┘
typ      └────┘ └─┘└┘└───┘└┘└┘   └┘└─┘└┘
doc      └────┘ └─┘  └───┘  └┘   └┘   └┘
txt      └────┘ └─┘  └───┘  └┘   └┘   └┘
par      └────┘ └─┘  └───┘  └┘   └┘   └┘
pid            └─┘  └───┘  └┘   └┘   
st   ──────────────────────────────────┘└─
2825  end
st   ──┘
2826  
2827  theorem mem_sections_length {L : list (list α)} {f} (h : f ∈ sections L) : length f = length L :=
id                                    └──┘  └──┘               └──────┘     └────┘   └────┘ 
src                                   └──┘  └──┘                 └──────┘      └────┘    └────┘
typ                                   └──┘  └──┘               └──────┘     └────┘   └────┘ 
doc                                                               └──────┘
2828  forall₂_length_eq (mem_sections.1 h)
id   └───────────────┘  └──────────┘  
src  └───────────────┘  └──────────┘
typ  └───────────────┘  └──────────┘  
2829  
2830  lemma rel_sections {r : α → β → Prop} : (forall₂ (forall₂ r) ⇒ forall₂ (forall₂ r)) sections sections
id                                          └─────┘  └─────┘    └─────┘  └─────┘    └──────┘ └──────┘
src                                           └─────┘  └─────┘     └─────┘  └─────┘     └──────┘ └──────┘
typ                                         └─────┘  └─────┘    └─────┘  └─────┘    └──────┘ └──────┘
doc                                                                                      └──────┘ └──────┘
2831  | _ _ forall₂.nil := forall₂.cons forall₂.nil forall₂.nil
id         └─────────┘    └──────────┘ └─────────┘ └─────────┘
src        └─────────┘    └──────────┘ └─────────┘ └─────────┘
typ        └─────────┘    └──────────┘ └─────────┘ └─────────┘
2832  | _ _ (forall₂.cons h₀ h₁) :=
id          └──────────┘ └┘ └┘
src         └──────────┘
typ         └──────────┘ └┘ └┘
2833    rel_bind (rel_sections h₁) (assume _ _ hl, rel_map (assume _ _ ha, forall₂.cons ha hl) h₀)
id     └──────┘  └──────────┘               └┘  └─────┘           └┘  └──────────┘ └┘ └┘
src    └──────┘                                   └─────┘                 └──────────┘
typ    └──────┘  └──────────┘               └┘  └─────┘           └┘  └──────────┘ └┘ └┘
2834  
2835  /- permutations -/
2836  
2837  section permutations
2838  
2839  @[simp] theorem permutations_aux_nil (is : list α) : permutations_aux [] is = [] :=
id                                              └──┘     └──────────────┘ └┘ └┘  └┘
src                                             └──┘      └──────────────┘ └┘     └┘
typ                                             └──┘     └──────────────┘ └┘ └┘  └┘
doc    └──┘
2840  by rw [permutations_aux, permutations_aux.rec]
id          └──────────────┘  └──────────────────┘
src     └──┘└──────────────┘└┘└──────────────────┘└─
typ     └──┘└──────────────┘└┘└──────────────────┘└─
doc     └──┘                └┘                    └─
txt     └──┘                └┘                    └─
par     └──┘                └┘                    └─
pid       └┘                └┘                    
st     └───────────────────┘└────────────────────┘
2841  
src  
typ  
doc  
txt  
par  
pid  
st   
2842  @[simp] theorem permutations_aux_cons (t : α) (ts is : list α) :
id                                                         └──┘ 
src                                                         └──┘
typ                                                        └──┘ 
doc    └──┘
2843    permutations_aux (t :: ts) is = foldr (λy r, (permutations_aux2 t ts r y id).2)
id     └──────────────┘   └┘ └┘  └┘  └───┘       └───────────────┘  └┘   └┘ 
src    └──────────────┘    └┘         └───┘         └───────────────┘          └┘ 
typ    └──────────────┘   └┘ └┘  └┘  └───┘       └───────────────┘  └┘   └┘ 
2844      (permutations_aux ts (t::is)) (permutations is) :=
id        └──────────────┘ └┘  └┘└┘    └──────────┘ └┘
src       └──────────────┘      └┘      └──────────┘
typ       └──────────────┘ └┘  └┘└┘    └──────────┘ └┘
doc                                     └──────────┘
2845  by rw [permutations_aux, permutations_aux.rec]; refl
id          └──────────────┘  └──────────────────┘
src     └──┘└──────────────┘└┘└──────────────────┘  └────
typ     └──┘└──────────────┘└┘└──────────────────┘  └────
doc     └──┘                └┘                      └────
txt     └──┘                └┘                      └────
par     └──┘                └┘                      └────
pid       └┘                └┘                          
st     └───────────────────┘└────────────────────┘└──────
2846  
src  
typ  
doc  
txt  
par  
pid  
st   
2847  end permutations
2848  
2849  /- insert -/
2850  section insert
2851  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
2852  
2853  @[simp] theorem insert_nil (a : α) : insert a nil = [a] := rfl
id                                       └────┘  └─┘      └─┘
src                                       └────┘   └─┘       └─┘
typ                                      └────┘  └─┘      └─┘
doc    └──┘
2854  
2855  theorem insert.def (a : α) (l : list α) : insert a l = if a ∈ l then l else a :: l := rfl
id                                  └──┘     └────┘                      └┘     └─┘
src                                  └──┘      └────┘                            └┘      └─┘
typ                                 └──┘     └────┘                      └┘     └─┘
2856  
2857  @[simp] theorem insert_of_mem {a : α} {l : list α} (h : a ∈ l) : insert a l = l :=
id                                             └──┘              └────┘    
src                                             └──┘                 └────┘     
typ                                            └──┘              └────┘    
doc    └──┘
2858  by simp only [insert.def, if_pos h]
id                 └────────┘  └────┘ 
src     └─────────┘└────────┘└┘└────┘ └─
typ     └─────────┘└────────┘└┘└────┘└─
doc     └─────────┘          └┘       └─
txt     └─────────┘          └┘       └─
par     └─────────┘          └┘       └─
pid         └──┘└┘          └┘       
st     └─────────────────────────────────
2859  
src  
typ  
doc  
txt  
par  
pid  
st   
2860  @[simp] theorem insert_of_not_mem {a : α} {l : list α} (h : a ∉ l) : insert a l = a :: l :=
id                                                 └──┘              └────┘     └┘ 
src                                                 └──┘                 └────┘        └┘
typ                                                └──┘              └────┘     └┘ 
doc    └──┘
2861  by simp only [insert.def, if_neg h]; split; refl
id                 └────────┘  └────┘ 
src     └─────────┘└────────┘└┘└────┘   └───┘  └────
typ     └─────────┘└────────┘└┘└────┘  └───┘  └────
doc     └─────────┘          └┘         └───┘  └────
txt     └─────────┘          └┘         └───┘  └────
par     └─────────┘          └┘         └───┘  └────
pid         └──┘└┘          └┘                    
st     └──────────────────────────────────────────────
2862  
src  
typ  
doc  
txt  
par  
pid  
st   
2863  @[simp] theorem mem_insert_iff {a b : α} {l : list α} : a ∈ insert b l ↔ a = b ∨ a ∈ l :=
id                                                └──┘       └────┘          
src                                                └──┘         └────┘              
typ                                               └──┘       └────┘          
doc    └──┘
2864  begin
st   └─────
2865    by_cases h' : b ∈ l,
id                     
src    └───────┘  └─┘ 
typ    └───────┘  └─┘
doc    └───────┘  └─┘  
txt    └───────┘  └─┘  
par    └───────┘  └─┘  
pid              └─┘  
st   ────────────────────┘└─
2866    { simp only [insert_of_mem h'],
id                  └───────────┘ └┘
src      └─────────┘└───────────┘  
typ      └─────────┘└───────────┘└┘
doc      └─────────┘               
txt      └─────────┘               
par      └─────────┘               
pid          └──┘└┘               
st   ───┘└──────────────────────────┘└─
2867      apply (or_iff_right_of_imp _).symm,
id              └─────────────────┘
src      └────┘ └─────────────────┘└──────┘
typ      └────┘ └─────────────────┘└──────┘
doc      └────┘                    └──────┘
txt      └────┘                    └──────┘
par      └────┘                    └──────┘
pid                               └─────┘
st   ─────────────────────────────────────┘└─
2868      exact λ e, e.symm ▸ h' },
id                   └───┘  └┘
src      └────┘ └──┘ └───┘  
typ      └────┘ └──┘ └───┘└┘
doc      └────┘ └──┘         
txt      └────┘ └──┘         
par      └────┘ └──┘         
pid            └──┘         
st   ──────────────────────────┘└┘
2869    simp only [insert_of_not_mem h', mem_cons_iff]
id                └───────────────┘ └┘  └──────────┘
src    └─────────┘└───────────────┘  └┘└──────────┘└┘
typ    └─────────┘└───────────────┘└┘└┘└──────────┘└┘
doc    └─────────┘                   └┘            └┘
txt    └─────────┘                   └┘            └┘
par    └─────────┘                   └┘            └┘
pid        └──┘└┘                   └┘            
st   ────────────────────────────────────────────────┘
2870  end
st   └─┘
2871  
2872  @[simp] theorem suffix_insert (a : α) (l : list α) : l <:+ insert a l :=
id                                             └──┘      └─┘ └────┘  
src                                             └──┘        └─┘ └────┘
typ                                            └──┘      └─┘ └────┘  
doc    └──┘                                                 └─┘
2873  by by_cases a ∈ l; [simp only [insert_of_mem h], simp only [insert_of_not_mem h, suffix_cons]]
id                              └───────────┘               └───────────────┘   └─────────┘
src     └───────┘    └─────────┘└───────────┘   └─────────┘└───────────────┘ └┘└─────────┘
typ     └───────┘  └─────────┘└───────────┘  └─────────┘└───────────────┘└┘└─────────┘
doc     └───────┘      └─────────┘                └─────────┘                  └┘           
txt     └───────┘      └─────────┘                └─────────┘                  └┘           
par     └───────┘      └─────────┘                └─────────┘                  └┘           
pid                       └──┘└┘                    └──┘└┘                  └┘           
st     └──────────────────────────────────────────────────────────────────────────────────────────┘
2874  
2875  @[simp] theorem mem_insert_self (a : α) (l : list α) : a ∈ insert a l :=
id                                               └──┘       └────┘  
src                                               └──┘         └────┘
typ                                              └──┘       └────┘  
doc    └──┘
2876  mem_insert_iff.2 (or.inl rfl)
id   └────────────┘   └────┘ └─┘
src  └────────────┘   └────┘ └─┘
typ  └────────────┘   └────┘ └─┘
2877  
2878  @[simp] theorem mem_insert_of_mem {a b : α} {l : list α} (h : a ∈ l) : a ∈ insert b l :=
id                                                   └──┘                └────┘  
src                                                   └──┘                    └────┘
typ                                                  └──┘                └────┘  
doc    └──┘
2879  mem_insert_iff.2 (or.inr h)
id   └────────────┘   └────┘ 
src  └────────────┘   └────┘
typ  └────────────┘   └────┘ 
2880  
2881  theorem eq_or_mem_of_mem_insert {a b : α} {l : list α} (h : a ∈ insert b l) : a = b ∨ a ∈ l :=
id                                                 └──┘          └────┘            
src                                                 └──┘            └────┘                
typ                                                └──┘          └────┘            
2882  mem_insert_iff.1 h
id   └────────────┘  
src  └────────────┘
typ  └────────────┘  
2883  
2884  @[simp] theorem length_insert_of_mem {a : α} {l : list α} (h : a ∈ l) :
id                                                    └──┘          
src                                                    └──┘           
typ                                                   └──┘          
doc    └──┘
2885    length (insert a l) = length l :=
id     └────┘  └────┘     └────┘ 
src    └────┘  └────┘       └────┘
typ    └────┘  └────┘     └────┘ 
2886  by rw insert_of_mem h
id         └───────────┘ 
src     └─┘└───────────┘ 
typ     └─┘└───────────┘
doc     └─┘              
txt     └─┘              
par     └─┘              
pid                     
st     └───────────────────
2887  
src  
typ  
doc  
txt  
par  
pid  
st   
2888  @[simp] theorem length_insert_of_not_mem {a : α} {l : list α} (h : a ∉ l) :
id                                                        └──┘          
src                                                        └──┘           
typ                                                       └──┘          
doc    └──┘
2889    length (insert a l) = length l + 1 :=
id     └────┘  └────┘     └────┘  
src    └────┘  └────┘       └────┘   
typ    └────┘  └────┘     └────┘  
2890  by rw insert_of_not_mem h; refl
id         └───────────────┘ 
src     └─┘└───────────────┘   └────
typ     └─┘└───────────────┘  └────
doc     └─┘                    └────
txt     └─┘                    └────
par     └─┘                    └────
pid                               
st     └─────────────────────────────
2891  
src  
typ  
doc  
txt  
par  
pid  
st   
2892  end insert
2893  
2894  /- erasep -/
2895  section erasep
2896  variables {p : α → Prop} [decidable_pred p]
id                             └────────────┘
src                            └────────────┘
typ                            └────────────┘
2897  
2898  @[simp] theorem erasep_nil : [].erasep p = [] := rfl
id                                └┘└────┘    └┘    └─┘
src                               └┘└────┘     └┘    └─┘
typ                               └┘└────┘    └┘    └─┘
doc    └──┘
2899  
2900  theorem erasep_cons (a : α) (l : list α) : (a :: l).erasep p = if p a then l else a :: l.erasep p := rfl
id                                   └──┘       └┘  └────┘                     └┘ └─────┘     └─┘
src                                   └──┘         └┘   └────┘                          └┘  └─────┘      └─┘
typ                                  └──┘       └┘  └────┘                     └┘ └─────┘     └─┘
2901  
2902  @[simp] theorem erasep_cons_of_pos {a : α} {l : list α} (h : p a) : (a :: l).erasep p = l :=
id                                                  └──┘               └┘  └────┘    
src                                                  └──┘                   └┘   └────┘    
typ                                                 └──┘               └┘  └────┘    
doc    └──┘
2903  by simp [erasep_cons, h]
id            └─────────┘  
src     └────┘└─────────┘└┘ └─
typ     └────┘└─────────┘└┘└─
doc     └────┘           └┘ └─
txt     └────┘           └┘ └─
par     └────┘           └┘ └─
pid                    └┘ 
st     └──────────────────────
2904  
src  
typ  
doc  
txt  
par  
pid  
st   
2905  @[simp] theorem erasep_cons_of_neg {a : α} {l : list α} (h : ¬ p a) : (a::l).erasep p = a :: l.erasep p :=
id                                                  └──┘               └┘ └────┘     └┘ └─────┘ 
src                                                  └──┘                   └┘  └────┘       └┘  └─────┘
typ                                                 └──┘               └┘ └────┘     └┘ └─────┘ 
doc    └──┘
2906  by simp [erasep_cons, h]
id            └─────────┘  
src     └────┘└─────────┘└┘ └─
typ     └────┘└─────────┘└┘└─
doc     └────┘           └┘ └─
txt     └────┘           └┘ └─
par     └────┘           └┘ └─
pid                    └┘ 
st     └──────────────────────
2907  
src  
typ  
doc  
txt  
par  
pid  
st   
2908  theorem erasep_of_forall_not {l : list α}
id                                     └──┘ 
src                                    └──┘
typ                                    └──┘ 
2909    (h : ∀ a ∈ l, ¬ p a) : l.erasep p = l :=
id                       └─────┘   
src                           └─────┘   
typ                      └─────┘   
2910  by induction l with _ _ ih; [refl,
id                              
src     └────────┘ └──────────┘  └──┘
typ     └────────┘└──────────┘  └──┘
doc     └────────┘ └──────────┘   └──┘
txt     └────────┘ └──────────┘   └──┘
par     └────────┘ └──────────┘   └──┘
pid               └─────────┘
st     └────────────────────────────────
2911    simp [h _ (or.inl rfl), ih (forall_mem_of_forall_mem_cons h)]]
id               └────┘ └─┘   └┘  └───────────────────────────┘ 
src    └────┘ └─┘ └────┘└─┘└─┘   └───────────────────────────┘ └┘
typ    └────┘└─┘ └────┘└─┘└─┘└┘ └───────────────────────────┘└┘
doc    └────┘ └─┘          └─┘                                 └┘
txt    └────┘ └─┘          └─┘                                 └┘
par    └────┘ └─┘          └─┘                                 └┘
pid         └─┘          └─┘                                 └┘
st   ───────────────────────────────────────────────────────────────┘
2912  
2913  theorem exists_of_erasep {l : list α} {a} (al : a ∈ l) (pa : p a) :
id                                 └──┘                        
src                                └──┘                
typ                                └──┘                        
2914    ∃ a l₁ l₂, (∀ b ∈ l₁, ¬ p b) ∧ p a ∧ l = l₁ ++ a :: l₂ ∧ l.erasep p = l₁ ++ l₂ :=
id       └┘ └┘       └┘            └┘ └┘  └┘ └┘  └─────┘   └┘ └┘ └┘
src                                          └┘   └┘      └─────┘       └┘
typ      └┘ └┘       └┘            └┘ └┘  └┘ └┘  └─────┘   └┘ └┘ └┘
2915  begin
st   └─────
2916    induction l with b l IH, {cases al},
id                                    └┘
src    └────────┘ └──────────┘   └────┘
typ    └────────┘└──────────┘   └────┘└┘
doc    └────────┘ └──────────┘   └────┘
txt    └────────┘ └──────────┘   └────┘
par    └────────┘ └──────────┘   └────┘
pid              └─────────┘        
st   ────────────────────────┘└─────────┘└┘
2917    by_cases pb : p b,
id                    
src    └───────┘  └─┘ 
typ    └───────┘  └─┘
doc    └───────┘  └─┘ 
txt    └───────┘  └─┘ 
par    └───────┘  └─┘ 
pid              └─┘ 
st   ──────────────────┘└─
2918    { exact ⟨b, [], l, forall_mem_nil _, pb, by simp [pb]⟩ },
id                      └────────────┘    └┘           └┘
src      └────┘  └┘  └┘ └┘└────────────┘└──┘  └┘  └────┘  └┘
typ      └────┘ └┘  └┘└┘└────────────┘└──┘└┘└┘  └────┘└┘└┘
doc      └────┘  └┘  └┘ └┘              └──┘  └┘  └────┘  └┘
txt      └────┘  └┘  └┘ └┘              └──┘  └┘  └────┘  └┘
par      └────┘  └┘  └┘ └┘              └──┘  └┘  └────┘  └┘
pid             └┘  └┘ └┘              └──┘  └┘  └─────┘  └┘
st   ───┘└───────────────────────────────────────┘└────────┘└┘└┘
2919    { rcases al with rfl | al, {exact pb.elim pa},
id              └┘                       └─────┘ └┘
src      └─────┘  └────────────┘   └────┘└─────┘
typ      └─────┘└┘└────────────┘   └────┘└─────┘└┘
doc      └─────┘  └────────────┘   └────┘       
txt      └─────┘  └────────────┘   └────┘       
par      └─────┘  └────────────┘   └────┘       
pid              └────────────┘               
st   ──────────────────────────┘└─────────────────┘└┘
2920      rcases IH al with ⟨c, l₁, l₂, h₁, h₂, h₃, h₄⟩,
id              └┘ └┘
src      └─────┘    └───────────────────────────────┘
typ      └─────┘└┘└┘└───────────────────────────────┘
doc      └─────┘    └───────────────────────────────┘
txt      └─────┘    └───────────────────────────────┘
par      └─────┘    └───────────────────────────────┘
pid                └───────────────────────────────┘
st   ────────────────────────────────────────────────┘└─
2921      exact ⟨c, b::l₁, l₂, forall_mem_cons.2 ⟨pb, h₁⟩,
id                  └┘  └┘  └─────────────┘    └┘  └┘
src      └────┘  └┘     └┘  └┘└─────────────┘└─┘   └┘  └──
typ      └────┘ └┘  └┘└┘└┘└┘└─────────────┘└─┘ └┘└┘└┘└──
doc      └────┘  └┘     └┘  └┘               └─┘   └┘  └──
txt      └────┘  └┘     └┘  └┘               └─┘   └┘  └──
par      └────┘  └┘     └┘  └┘               └─┘   └┘  └──
pid             └┘     └┘  └┘               └─┘   └┘  └──
st   ─────────────────────────────────────────────────────
2922        h₂, by rw h₃; refl, by simp [pb, h₄]⟩ }
id         └┘        └┘                 └┘  └┘
src  ─────┘  └┘  └─┘  └┘└──┘└┘  └────┘  └┘  └┘
typ  ─────┘└┘└┘  └─┘└┘└┘└──┘└┘  └────┘└┘└┘└┘└┘
doc  ─────┘  └┘  └─┘  └┘└──┘└┘  └────┘  └┘  └┘
txt  ─────┘  └┘  └─┘  └┘└──┘└┘  └────┘  └┘  └┘
par  ─────┘  └┘  └─┘  └┘└──┘└┘  └────┘  └┘  └┘
pid  ─────┘  └┘  └──┘  └──────┘  └─────┘  └┘  └┘
st   ───────────┘└──────────┘└──┘└────────────┘└┘└─
2923  end
st   ──┘
2924  
2925  theorem exists_or_eq_self_of_erasep (p : α → Prop) [decidable_pred p] (l : list α) :
id                                                      └────────────┘        └──┘ 
src                                                      └────────────┘         └──┘
typ                                                     └────────────┘        └──┘ 
2926    l.erasep p = l ∨ ∃ a l₁ l₂, (∀ b ∈ l₁, ¬ p b) ∧ p a ∧ l = l₁ ++ a :: l₂ ∧ l.erasep p = l₁ ++ l₂ :=
id     └─────┘       └┘ └┘       └┘            └┘ └┘  └┘ └┘  └─────┘   └┘ └┘ └┘
src     └─────┘                                             └┘   └┘      └─────┘       └┘
typ    └─────┘       └┘ └┘       └┘            └┘ └┘  └┘ └┘  └─────┘   └┘ └┘ └┘
2927  begin
st   └─────
2928    by_cases h : ∃ a ∈ l, p a,
id                        
src    └───────┘ └─┘└───┘  
typ    └───────┘ └─┘└───┘
doc    └───────┘ └─┘ └───┘   
txt    └───────┘ └─┘ └───┘   
par    └───────┘ └─┘ └───┘   
pid             └─┘ └───┘   
st   ──────────────────────────┘└─
2929    { rcases h with ⟨a, ha, pa⟩,
id              
src      └─────┘ └───────────────┘
typ      └─────┘└───────────────┘
doc      └─────┘ └───────────────┘
txt      └─────┘ └───────────────┘
par      └─────┘ └───────────────┘
pid             └───────────────┘
st   ───┘└───────────────────────┘└─
2930      exact or.inr (exists_of_erasep ha pa) },
id             └────┘  └──────────────┘ └┘ └┘
src      └────┘└────┘ └──────────────┘    └┘
typ      └────┘└────┘ └──────────────┘└┘└┘└┘
doc      └────┘                           └┘
txt      └────┘                           └┘
par      └────┘                           └┘
pid                                      
st   ─────────────────────────────────────────┘└┘
2931    { simp at h, exact or.inl (erasep_of_forall_not h) }
id                        └────┘  └──────────────────┘ 
src      └───────┘  └────┘└────┘ └──────────────────┘ └┘
typ      └───────┘  └────┘└────┘ └──────────────────┘└┘
doc      └───────┘  └────┘                            └┘
txt      └───────┘  └────┘                            └┘
par      └───────┘  └────┘                            └┘
pid          └──┘                                   
st   ────────────┘└──────────────────────────────────────┘└─
2932  end
st   ──┘
2933  
2934  @[simp] theorem length_erasep_of_mem {l : list α} {a} (al : a ∈ l) (pa : p a) :
id                                             └──┘                        
src                                            └──┘                
typ                                            └──┘                        
doc    └──┘
2935   length (l.erasep p) = pred (length l) :=
id    └────┘  └─────┘    └──┘  └────┘ 
src   └────┘   └─────┘     └──┘  └────┘
typ   └────┘  └─────┘    └──┘  └────┘ 
2936  by rcases exists_of_erasep al pa with ⟨_, l₁, l₂, _, _, e₁, e₂⟩;
id             └──────────────┘ └┘ └┘
src     └─────┘└──────────────┘    └─────────────────────────────┘
typ     └─────┘└──────────────┘└┘└┘└─────────────────────────────┘
doc     └─────┘                    └─────────────────────────────┘
txt     └─────┘                    └─────────────────────────────┘
par     └─────┘                    └─────────────────────────────┘
pid                               └─────────────────────────────┘
st     └──────────────────────────────────────────────────────────────
2937     rw e₂; simp [-add_comm, e₁]; refl
id         └┘                   └┘
src     └─┘    └───────────────┘    └────
typ     └─┘└┘  └───────────────┘└┘  └────
doc     └─┘    └───────────────┘    └────
txt     └─┘    └───────────────┘    └────
par     └─┘    └───────────────┘    └────
pid               └──────────┘        
st   ─────┘└┘└────────────────────────────
2938  
src  
typ  
doc  
txt  
par  
pid  
st   
2939  theorem erasep_append_left {a : α} (pa : p a) :
id                                            
typ                                           
2940    ∀ {l₁ : list α} (l₂), a ∈ l₁ → (l₁++l₂).erasep p = l₁.erasep p ++ l₂
id            └──┘    └┘     └┘    └┘└┘└┘ └────┘    └┘└─────┘  └┘ └┘
src            └──┘                     └┘   └────┘       └─────┘   └┘
typ           └──┘    └┘     └┘    └┘└┘└┘ └────┘    └┘└─────┘  └┘ └┘
2941  | (x::xs) l₂ h := begin
id       └┘
src      └┘
typ      └┘
st                     └─────
2942    by_cases h' : p x; simp [h'],
id                            └┘
src    └───────┘  └─┘    └────┘  
typ    └───────┘  └─┘  └────┘└┘
doc    └───────┘  └─┘    └────┘  
txt    └───────┘  └─┘    └────┘  
par    └───────┘  └─┘    └────┘  
pid              └─┘          
st   ─────────────────────────────┘└─
2943    rw erasep_append_left l₂ (mem_of_ne_of_mem (mt _ h') h),
id        └────────────────┘ └┘  └──────────────┘  └┘   └┘  
src    └─┘                     └──────────────┘ └┘└─┘  └┘ 
typ    └─┘└────────────────┘└┘ └──────────────┘ └┘└─┘└┘└┘
doc    └─┘                                        └─┘  └┘ 
txt    └─┘                                        └─┘  └┘ 
par    └─┘                                        └─┘  └┘ 
pid                                              └─┘  └┘ 
st   ────────────────────────────────────────────────────────┘└─
2944    rintro rfl, exact pa
id                       └┘
src    └────────┘  └────┘  
typ    └────────┘  └────┘└┘
doc    └────────┘  └────┘  
txt    └────────┘  └────┘  
par    └────────┘  └────┘  
pid          └──┘         
st   ───────────┘└─────────┘
2945  end
st   └─┘
2946  
2947  theorem erasep_append_right : ∀ {l₁ : list α} (l₂), (∀ b ∈ l₁, ¬ p b) → (l₁++l₂).erasep p = l₁ ++ l₂.erasep p
id                                        └──┘    └┘         └┘         └┘└┘└┘ └────┘    └┘ └┘ └┘└─────┘ 
src                                        └──┘                                └┘   └────┘        └┘   └─────┘
typ                                       └──┘    └┘         └┘         └┘└┘└┘ └────┘    └┘ └┘ └┘└─────┘ 
2948  | []      l₂ h := rfl
id     └┘              └─┘
src    └┘              └─┘
typ    └┘              └─┘
2949  | (x::xs) l₂ h := by simp [(forall_mem_cons.1 h).1,
id       └┘                      └─────────────┘   
src      └┘               └────┘ └─────────────┘└─┘ └────
typ      └┘               └────┘ └─────────────┘└─┘└────
doc                       └────┘                └─┘ └────
txt                       └────┘                └─┘ └────
par                       └────┘                └─┘ └────
pid                                           └─┘ └────
st                       └───────────────────────────────
2950    erasep_append_right _ (forall_mem_cons.1 h).2]
id     └─────────────────┘    └─────────────┘   
src  ─┘                   └─┘ └─────────────┘└─┘ └────
typ  ─┘└─────────────────┘└─┘ └─────────────┘└─┘└────
doc  ─┘                   └─┘                └─┘ └────
txt  ─┘                   └─┘                └─┘ └────
par  ─┘                   └─┘                └─┘ └────
pid  ─┘                   └─┘                └─┘ └──┘
st   ─────────────────────────────────────────────────
2951  
src  
typ  
doc  
txt  
par  
pid  
st   
2952  theorem erasep_sublist (l : list α) : l.erasep p <+ l :=
id                               └──┘     └─────┘  └┘ 
src                              └──┘       └─────┘   └┘
typ                              └──┘     └─────┘  └┘ 
2953  by rcases exists_or_eq_self_of_erasep p l with h | ⟨c, l₁, l₂, h₁, h₂, h₃, h₄⟩;
id             └─────────────────────────┘  
src     └─────┘└─────────────────────────┘  └───────────────────────────────────┘
typ     └─────┘└─────────────────────────┘└───────────────────────────────────┘
doc     └─────┘                             └───────────────────────────────────┘
txt     └─────┘                             └───────────────────────────────────┘
par     └─────┘                             └───────────────────────────────────┘
pid                                        └───────────────────────────────────┘
st     └─────────────────────────────────────────────────────────────────────────────
2954     [rw h, {rw [h₄, h₃], simp}]
id                └┘  └┘
src     └─┘    └──┘  └┘    └──┘
typ     └─┘   └──┘└┘└┘└┘  └──┘
doc      └─┘    └──┘  └┘    └──┘
txt      └─┘    └──┘  └┘    └──┘
par      └─┘    └──┘  └┘    └──┘
pid              └┘  └┘  
st   ──────┘└┘└─────┘└──┘└─────┘└┘
2955  
2956  theorem erasep_subset (l : list α) : l.erasep p ⊆ l :=
id                              └──┘     └─────┘   
src                             └──┘       └─────┘   
typ                             └──┘     └─────┘   
2957  subset_of_sublist (erasep_sublist l)
id   └───────────────┘  └────────────┘ 
src  └───────────────┘  └────────────┘
typ  └───────────────┘  └────────────┘ 
2958  
2959  theorem erasep_sublist_erasep {l₁ l₂ : list α} (s : l₁ <+ l₂) : l₁.erasep p <+ l₂.erasep p :=
id                                          └──┘        └┘ └┘ └┘    └┘└─────┘  └┘ └┘└─────┘ 
src                                         └──┘            └┘         └─────┘   └┘   └─────┘
typ                                         └──┘        └┘ └┘ └┘    └┘└─────┘  └┘ └┘└─────┘ 
2960  begin
st   └─────
2961    induction s,
id               
src    └────────┘
typ    └────────┘
doc    └────────┘
txt    └────────┘
par    └────────┘
pid             
st   ────────────┘└─
2962    case list.sublist.slnil { refl },
src    └────────────────────────┘└───┘
typ    └────────────────────────┘└───┘
doc    └────────────────────────┘└───┘
txt    └────────────────────────┘└───┘
par    └────────────────────────┘└───┘
pid        └─────────────────┘└──────┘
st   ──────────────────────────┘└────┘└┘
2963    case list.sublist.cons : l₁ l₂ a s IH {
src    └───────────────────────────────────────
typ    └───────────────────────────────────────
doc    └───────────────────────────────────────
txt    └───────────────────────────────────────
par    └───────────────────────────────────────
pid        └────────────────┘└─────────────┘└──
st   ────────────────────────────────────────┘
2964      by_cases h : p a; simp [h],
id                             
src  ───┘└───────┘ └─┘  └┘└────┘ └─
typ  ───┘└───────┘ └─┘└┘└────┘└─
doc  ───┘└───────┘ └─┘  └┘└────┘ └─
txt  ───┘└───────┘ └─┘  └┘└────┘ └─
par  ───┘└───────┘ └─┘  └┘└────┘ └─
pid  ────────────┘ └─┘  └──────┘ └──
st   ─────────────────────────────┘└─
2965      exacts [IH.trans (erasep_sublist _), IH.cons _ _ _] },
id               └──────┘  └────────────┘     └─────┘
src  ───┘└──────┘└──────┘ └────────────┘└───┘└─────┘└──────┘
typ  ───┘└──────┘└──────┘ └────────────┘└───┘└─────┘└──────┘
doc  ───┘└──────┘                       └───┘       └──────┘
txt  ───┘└──────┘                       └───┘       └──────┘
par  ───┘└──────┘                       └───┘       └──────┘
pid  ───────────┘                       └───┘       └───────┘
st   ───────────────────────────────────────────────────────┘└┘
2966    case list.sublist.cons2 : l₁ l₂ a s IH {
src    └────────────────────────────────────────
typ    └────────────────────────────────────────
doc    └────────────────────────────────────────
txt    └────────────────────────────────────────
par    └────────────────────────────────────────
pid        └─────────────────┘└─────────────┘└──
st   ─────────────────────────────────────────┘
2967      by_cases h : p a; simp [h],
id                             
src  ───┘└───────┘ └─┘  └┘└────┘ └─
typ  ───┘└───────┘ └─┘└┘└────┘└─
doc  ───┘└───────┘ └─┘  └┘└────┘ └─
txt  ───┘└───────┘ └─┘  └┘└────┘ └─
par  ───┘└───────┘ └─┘  └┘└────┘ └─
pid  ────────────┘ └─┘  └──────┘ └──
st   ─────────────────────────────┘└─
2968      exacts [s, IH.cons2 _ _ _] }
id                 └──────┘
src  ───┘└──────┘ └┘└──────┘└──────┘└┘
typ  ───┘└──────┘└┘└──────┘└──────┘└┘
doc  ───┘└──────┘ └┘        └──────┘└┘
txt  ───┘└──────┘ └┘        └──────┘└┘
par  ───┘└──────┘ └┘        └──────┘└┘
pid  ───────────┘ └┘        └───────┘
st   ──────────────────────────────┘
2969  end
st   └─┘
2970  
2971  theorem mem_of_mem_erasep {a : α} {l : list α} : a ∈ l.erasep p → a ∈ l :=
id                                         └──┘       └─────┘      
src                                         └──┘          └─────┘       
typ                                        └──┘       └─────┘      
2972  @erasep_subset _ _ _ _ _
id    └───────────┘
src   └───────────┘
typ   └───────────┘
2973  
2974  @[simp] theorem mem_erasep_of_neg {a : α} {l : list α} (pa : ¬ p a) : a ∈ l.erasep p ↔ a ∈ l :=
id                                                 └──┘                 └─────┘     
src                                                 └──┘                      └─────┘      
typ                                                └──┘                 └─────┘     
doc    └──┘
2975  ⟨mem_of_mem_erasep, λ al, begin
id    └───────────────┘    └┘
src   └───────────────┘
typ   └───────────────┘    └┘
st                             └─────
2976    rcases exists_or_eq_self_of_erasep p l with h | ⟨c, l₁, l₂, h₁, h₂, h₃, h₄⟩,
id            └─────────────────────────┘  
src    └─────┘└─────────────────────────┘  └───────────────────────────────────┘
typ    └─────┘└─────────────────────────┘└───────────────────────────────────┘
doc    └─────┘                             └───────────────────────────────────┘
txt    └─────┘                             └───────────────────────────────────┘
par    └─────┘                             └───────────────────────────────────┘
pid                                       └───────────────────────────────────┘
st   ────────────────────────────────────────────────────────────────────────────┘└─
2977    { rwa h },
id           
src      └──┘ 
typ      └──┘
doc      └──┘ 
txt      └──┘ 
par      └──┘ 
pid          
st   ───┘└────┘└┘
2978    { rw h₄, rw h₃ at al,
id          └┘     └┘
src      └─┘    └─┘  └────┘
typ      └─┘└┘  └─┘└┘└────┘
doc      └─┘    └─┘  └────┘
txt      └─┘    └─┘  └────┘
par      └─┘    └─┘  └────┘
pid                └────┘
st   ────────┘└───────────┘└─
2979      have : a ≠ c, {rintro rfl, exact pa.elim h₂},
id                                     └─────┘ └┘
src      └─────┘     └────────┘  └────┘└─────┘
typ      └─────┘   └────────┘  └────┘└─────┘└┘
doc      └─────┘      └────────┘  └────┘       
txt      └─────┘      └────────┘  └────┘       
par      └─────┘      └────────┘  └────┘       
pid      └───┘└┘            └──┘              
st   ───────────────┘└───────────┘└────────────────┘└┘
2980      simpa [this] using al }
id              └──┘        └┘
src      └─────┘    └──────┘  
typ      └─────┘└──┘└──────┘└┘
doc      └─────┘    └──────┘  
txt      └─────┘    └──────┘  
par      └─────┘    └──────┘  
pid               └────┘  
st   ─────────────────────────┘└─
2981  end⟩
st   ──┘
2982  
2983  theorem erasep_map (f : β → α) :
id                              
typ                             
2984    ∀ (l : list β), (map f l).erasep p = map f (l.erasep (p ∘ f))
id           └──┘     └─┘   └────┘    └─┘   └─────┘    
src           └──┘      └─┘     └────┘     └─┘     └─────┘    
typ          └──┘     └─┘   └────┘    └─┘   └─────┘    
2985  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
2986  | (b::l) := by by_cases p (f b); simp [h, erasep_map l]
id       └┘                                └────────┘ 
src      └┘         └───────┘      └────┘ └┘           └─
typ      └┘         └───────┘   └────┘└┘└────────┘└─
doc                 └───────┘      └────┘ └┘           └─
txt                 └───────┘      └────┘ └┘           └─
par                 └───────┘      └────┘ └┘           └─
pid                                    └┘           
st                 └─────────────────────────────────────────
2987  
src  
typ  
doc  
txt  
par  
pid  
st   
2988  @[simp] theorem extractp_eq_find_erasep :
doc    └──┘
2989    ∀ l : list α, extractp p l = (find p l, erasep p l)
id          └──┘   └──────┘    └──┘    └────┘  
src          └──┘    └──────┘      └──┘      └────┘
typ         └──┘   └──────┘    └──┘    └────┘  
doc                                  └──┘
2990  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
2991  | (a::l) := by by_cases pa : p a; simp [extractp, pa, extractp_eq_find_erasep l]
id       └┘                                └──────┘  └┘  └─────────────────────┘ 
src      └┘         └───────┘  └─┘    └────┘└──────┘└┘  └┘                        └─
typ      └┘         └───────┘  └─┘  └────┘└──────┘└┘└┘└┘└─────────────────────┘└─
doc                 └───────┘  └─┘    └────┘        └┘  └┘                        └─
txt                 └───────┘  └─┘    └────┘        └┘  └┘                        └─
par                 └───────┘  └─┘    └────┘        └┘  └┘                        └─
pid                           └─┘                └┘  └┘                        
st                 └──────────────────────────────────────────────────────────────────
2992  
src  
typ  
doc  
txt  
par  
pid  
st   
2993  end erasep
2994  
2995  /- erase -/
2996  section erase
2997  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
2998  
2999  @[simp] theorem erase_nil (a : α) : [].erase a = [] := rfl
id                                      └┘└───┘    └┘    └─┘
src                                      └┘└───┘     └┘    └─┘
typ                                     └┘└───┘    └┘    └─┘
doc    └──┘
3000  
3001  theorem erase_cons (a b : α) (l : list α) : (b :: l).erase a = if b = a then l else b :: l.erase a := rfl
id                                    └──┘       └┘  └───┘                      └┘ └────┘     └─┘
src                                    └──┘         └┘   └───┘                           └┘  └────┘      └─┘
typ                                   └──┘       └┘  └───┘                      └┘ └────┘     └─┘
3002  
3003  @[simp] theorem erase_cons_head (a : α) (l : list α) : (a :: l).erase a = l :=
id                                               └──┘       └┘  └───┘    
src                                               └──┘         └┘   └───┘    
typ                                              └──┘       └┘  └───┘    
doc    └──┘
3004  by simp only [erase_cons, if_pos rfl]
id                 └────────┘  └────┘ └─┘
src     └─────────┘└────────┘└┘└────┘└─┘└─
typ     └─────────┘└────────┘└┘└────┘└─┘└─
doc     └─────────┘          └┘         └─
txt     └─────────┘          └┘         └─
par     └─────────┘          └┘         └─
pid         └──┘└┘          └┘         
st     └───────────────────────────────────
3005  
src  
typ  
doc  
txt  
par  
pid  
st   
3006  @[simp] theorem erase_cons_tail {a b : α} (l : list α) (h : b ≠ a) : (b::l).erase a = b :: l.erase a :=
id                                                 └──┘               └┘ └───┘     └┘ └────┘ 
src                                                 └──┘                   └┘  └───┘       └┘  └────┘
typ                                                └──┘               └┘ └───┘     └┘ └────┘ 
doc    └──┘
3007  by simp only [erase_cons, if_neg h]; split; refl
id                 └────────┘  └────┘ 
src     └─────────┘└────────┘└┘└────┘   └───┘  └────
typ     └─────────┘└────────┘└┘└────┘  └───┘  └────
doc     └─────────┘          └┘         └───┘  └────
txt     └─────────┘          └┘         └───┘  └────
par     └─────────┘          └┘         └───┘  └────
pid         └──┘└┘          └┘                    
st     └──────────────────────────────────────────────
3008  
src  
typ  
doc  
txt  
par  
pid  
st   
3009  theorem erase_eq_erasep (a : α) (l : list α) : l.erase a = l.erasep (eq a) :=
id                                       └──┘     └────┘   └─────┘  └┘ 
src                                       └──┘       └────┘     └─────┘  └┘
typ                                      └──┘     └────┘   └─────┘  └┘ 
3010  by { induction l with b l, {refl},
id                  
src       └────────┘ └───────┘   └──┘
typ       └────────┘└───────┘   └──┘
doc       └────────┘ └───────┘   └──┘
txt       └────────┘ └───────┘   └──┘
par       └────────┘ └───────┘   └──┘
pid                 └──────┘
st     └─────────────────────┘└─────┘└┘
3011    by_cases a = b; [simp [h], simp [h, ne.symm h, *]] }
id                                   └─────┘ 
src    └───────┘    └────┘   └────┘ └┘└─────┘ └──┘
typ    └───────┘  └────┘  └────┘└┘└─────┘└──┘
doc    └───────┘      └────┘   └────┘ └┘        └──┘
txt    └───────┘      └────┘   └────┘ └┘        └──┘
par    └───────┘      └────┘   └────┘ └┘        └──┘
pid                              └┘        └──┘
st   ───────────────────────────────────────────────────┘└─┘
3012  
3013  @[simp] theorem erase_of_not_mem {a : α} {l : list α} (h : a ∉ l) : l.erase a = l :=
id                                                └──┘              └────┘   
src                                                └──┘                  └────┘   
typ                                               └──┘              └────┘   
doc    └──┘
3014  by rw [erase_eq_erasep, erasep_of_forall_not]; rintro b h' rfl; exact h h'
id          └─────────────┘  └──────────────────┘                           └┘
src     └──┘└─────────────┘└┘└──────────────────┘  └─────────────┘  └────┘   
typ     └──┘└─────────────┘└┘└──────────────────┘  └─────────────┘  └────┘└┘
doc     └──┘               └┘                      └─────────────┘  └────┘   
txt     └──┘               └┘                      └─────────────┘  └────┘   
par     └──┘               └┘                      └─────────────┘  └────┘   
pid       └┘               └┘                            └───────┘          
st     └──────────────────┘└────────────────────┘└─────────────────────────────
3015  
src  
typ  
doc  
txt  
par  
pid  
st   
3016  theorem exists_erase_eq {a : α} {l : list α} (h : a ∈ l) :
id                                       └──┘          
src                                       └──┘           
typ                                      └──┘          
3017    ∃ l₁ l₂, a ∉ l₁ ∧ l = l₁ ++ a :: l₂ ∧ l.erase a = l₁ ++ l₂ :=
id      └┘ └┘   └┘    └┘ └┘  └┘ └┘  └────┘   └┘ └┘ └┘
src                        └┘   └┘      └────┘       └┘
typ     └┘ └┘   └┘    └┘ └┘  └┘ └┘  └────┘   └┘ └┘ └┘
3018  by rcases exists_of_erasep h rfl with ⟨_, l₁, l₂, h₁, rfl, h₂, h₃⟩;
id             └──────────────┘  └─┘
src     └─────┘└──────────────┘ └─┘└────────────────────────────────┘
typ     └─────┘└──────────────┘└─┘└────────────────────────────────┘
doc     └─────┘                    └────────────────────────────────┘
txt     └─────┘                    └────────────────────────────────┘
par     └─────┘                    └────────────────────────────────┘
pid                               └────────────────────────────────┘
st     └─────────────────────────────────────────────────────────────────
3019     rw erase_eq_erasep; exact ⟨l₁, l₂, λ h, h₁ _ h rfl, h₂, h₃⟩
id         └─────────────┘         └┘  └┘       └┘     └─┘  └┘  └┘
src     └─┘└─────────────┘  └────┘   └┘  └┘ └──┘  └─┘ └─┘└┘  └┘  └─
typ     └─┘└─────────────┘  └────┘ └┘└┘└┘└┘ └──┘└┘└─┘ └─┘└┘└┘└┘└┘└─
doc     └─┘                 └────┘   └┘  └┘ └──┘  └─┘    └┘  └┘  └─
txt     └─┘                 └────┘   └┘  └┘ └──┘  └─┘    └┘  └┘  └─
par     └─┘                 └────┘   └┘  └┘ └──┘  └─┘    └┘  └┘  └─
pid                                └┘  └┘ └──┘  └─┘    └┘  └┘  
st   ─────┘└─────────────┘└─────────────────────────────────────────
3020  
src  
typ  
doc  
txt  
par  
pid  
st   
3021  @[simp] theorem length_erase_of_mem {a : α} {l : list α} (h : a ∈ l) : length (l.erase a) = pred (length l) :=
id                                                   └──┘              └────┘  └────┘    └──┘  └────┘ 
src                                                   └──┘                 └────┘   └────┘     └──┘  └────┘
typ                                                  └──┘              └────┘  └────┘    └──┘  └────┘ 
doc    └──┘
3022  by rw erase_eq_erasep; exact length_erasep_of_mem h rfl
id         └─────────────┘        └──────────────────┘  └─┘
src     └─┘└─────────────┘  └────┘└──────────────────┘ └─┘
typ     └─┘└─────────────┘  └────┘└──────────────────┘└─┘
doc     └─┘                 └────┘                        
txt     └─┘                 └────┘                        
par     └─┘                 └────┘                        
pid                                                     
st     └─────────────────────────────────────────────────────
3023  
src  
typ  
doc  
txt  
par  
pid  
st   
3024  theorem erase_append_left {a : α} {l₁ : list α} (l₂) (h : a ∈ l₁) :
id                                          └──┘               └┘
src                                          └──┘                
typ                                         └──┘               └┘
3025    (l₁++l₂).erase a = l₁.erase a ++ l₂ :=
id      └┘└┘└┘ └───┘    └┘└────┘  └┘ └┘
src       └┘   └───┘       └────┘   └┘
typ     └┘└┘└┘ └───┘    └┘└────┘  └┘ └┘
3026  by simp [erase_eq_erasep]; exact erasep_append_left (by refl) l₂ h
id            └─────────────┘         └────────────────┘           └┘ 
src     └────┘└─────────────┘  └────┘└────────────────┘   └──┘└┘   
typ     └────┘└─────────────┘  └────┘└────────────────┘   └──┘└┘└┘
doc     └────┘                 └────┘                     └──┘└┘   
txt     └────┘                 └────┘                     └──┘└┘   
par     └────┘                 └────┘                     └──┘└┘   
pid                                                    └─────┘   
st     └───────────────────────────────────────────────────┘└───┘└──────
3027  
src  
typ  
doc  
txt  
par  
pid  
st   
3028  theorem erase_append_right {a : α} {l₁ : list α} (l₂) (h : a ∉ l₁) :
id                                           └──┘               └┘
src                                           └──┘                
typ                                          └──┘               └┘
3029    (l₁++l₂).erase a = l₁ ++ l₂.erase a :=
id      └┘└┘└┘ └───┘    └┘ └┘ └┘└────┘ 
src       └┘   └───┘        └┘   └────┘
typ     └┘└┘└┘ └───┘    └┘ └┘ └┘└────┘ 
3030  by rw [erase_eq_erasep, erase_eq_erasep, erasep_append_right];
id          └─────────────┘  └─────────────┘  └─────────────────┘
src     └──┘└─────────────┘└┘└─────────────┘└┘└─────────────────┘
typ     └──┘└─────────────┘└┘└─────────────┘└┘└─────────────────┘
doc     └──┘               └┘               └┘                   
txt     └──┘               └┘               └┘                   
par     └──┘               └┘               └┘                   
pid       └┘               └┘               └┘                   
st     └──────────────────┘└───────────────┘└───────────────────┘└─
3031     rintro b h' rfl; exact h h'
id                              └┘
src     └─────────────┘  └────┘   
typ     └─────────────┘  └────┘└┘
doc     └─────────────┘  └────┘   
txt     └─────────────┘  └────┘   
par     └─────────────┘  └────┘   
pid           └───────┘          
st   ───────────────────────────────
3032  
src  
typ  
doc  
txt  
par  
pid  
st   
3033  theorem erase_sublist (a : α) (l : list α) : l.erase a <+ l :=
id                                     └──┘     └────┘  └┘ 
src                                     └──┘       └────┘   └┘
typ                                    └──┘     └────┘  └┘ 
3034  by rw erase_eq_erasep; apply erasep_sublist
id         └─────────────┘        └────────────┘
src     └─┘└─────────────┘  └────┘└────────────┘
typ     └─┘└─────────────┘  └────┘└────────────┘
doc     └─┘                 └────┘              
txt     └─┘                 └────┘              
par     └─┘                 └────┘              
pid                                           
st     └─────────────────────────────────────────
3035  
src  
typ  
doc  
txt  
par  
pid  
st   
3036  theorem erase_subset (a : α) (l : list α) : l.erase a ⊆ l :=
id                                    └──┘     └────┘   
src                                    └──┘       └────┘   
typ                                   └──┘     └────┘   
3037  subset_of_sublist (erase_sublist a l)
id   └───────────────┘  └───────────┘  
src  └───────────────┘  └───────────┘
typ  └───────────────┘  └───────────┘  
3038  
3039  theorem erase_sublist_erase (a : α) {l₁ l₂ : list α} (h : l₁ <+ l₂) : l₁.erase a <+ l₂.erase a :=
id                                               └──┘        └┘ └┘ └┘    └┘└────┘  └┘ └┘└────┘ 
src                                               └──┘            └┘         └────┘   └┘   └────┘
typ                                              └──┘        └┘ └┘ └┘    └┘└────┘  └┘ └┘└────┘ 
3040  by simp [erase_eq_erasep]; exact erasep_sublist_erasep h
id            └─────────────┘         └───────────────────┘ 
src     └────┘└─────────────┘  └────┘└───────────────────┘ 
typ     └────┘└─────────────┘  └────┘└───────────────────┘
doc     └────┘                 └────┘                      
txt     └────┘                 └────┘                      
par     └────┘                 └────┘                      
pid                                                     
st     └──────────────────────────────────────────────────────
3041  
src  
typ  
doc  
txt  
par  
pid  
st   
3042  theorem mem_of_mem_erase {a b : α} {l : list α} : a ∈ l.erase b → a ∈ l :=
id                                          └──┘       └────┘      
src                                          └──┘          └────┘       
typ                                         └──┘       └────┘      
3043  @erase_subset _ _ _ _ _
id    └──────────┘
src   └──────────┘
typ   └──────────┘
3044  
3045  @[simp] theorem mem_erase_of_ne {a b : α} {l : list α} (ab : a ≠ b) : a ∈ l.erase b ↔ a ∈ l :=
id                                                 └──┘                 └────┘     
src                                                 └──┘                      └────┘      
typ                                                └──┘                 └────┘     
doc    └──┘
3046  by rw erase_eq_erasep; exact mem_erasep_of_neg ab.symm
id         └─────────────┘        └───────────────┘ └─────┘
src     └─┘└─────────────┘  └────┘└───────────────┘└─────┘
typ     └─┘└─────────────┘  └────┘└───────────────┘└─────┘
doc     └─┘                 └────┘                        
txt     └─┘                 └────┘                        
par     └─┘                 └────┘                        
pid                                                     
st     └────────────────────────────────────────────────────
3047  
src  
typ  
doc  
txt  
par  
pid  
st   
3048  theorem erase_comm (a b : α) (l : list α) : (l.erase a).erase b = (l.erase b).erase a :=
id                                    └──┘      └────┘  └───┘     └────┘  └───┘  
src                                    └──┘        └────┘   └───┘       └────┘   └───┘
typ                                   └──┘      └────┘  └───┘     └────┘  └───┘  
3049  if ab : a = b then by rw ab else
id   └┘                    └┘
src  └┘                   └─┘  
typ  └┘                 └─┘└┘
doc                        └─┘  
txt                        └─┘  
par                        └─┘  
pid                            
st                        └─────┘
3050  if ha : a ∈ l then
id   └┘        
src  └┘        
typ  └┘        
3051  if hb : b ∈ l then match l, l.erase a, exists_erase_eq ha, hb with
id   └┘                      └────┘   └─────────────┘ └┘  └┘
src  └┘                          └────┘    └─────────────┘
typ  └┘                      └────┘   └─────────────┘ └┘  └┘
3052  | ._, ._, ⟨l₁, l₂, ha', rfl, rfl⟩, hb :=
id              └┘                └─┘
src                               └─┘
typ             └┘                └─┘
3053    if h₁ : b ∈ l₁ then
id     └┘       
src    └┘        
typ    └┘       
3054      by rw [erase_append_left _ h₁, erase_append_left _ h₁,
id              └───────────────┘   └┘  └───────────────┘   └┘
src         └──┘└───────────────┘└─┘  └┘└───────────────┘└─┘  └─
typ         └──┘└───────────────┘└─┘└┘└┘└───────────────┘└─┘└┘└─
doc         └──┘                 └─┘  └┘                 └─┘  └─
txt         └──┘                 └─┘  └┘                 └─┘  └─
par         └──┘                 └─┘  └┘                 └─┘  └─
pid           └┘                 └─┘  └┘                 └─┘  └─
st         └─────────────────────────┘└──────────────────────┘└─
3055             erase_append_right _ (mt mem_of_mem_erase ha'), erase_cons_head]
id              └────────────────┘    └┘ └──────────────┘ └─┘   └─────────────┘
src  ──────────┘└────────────────┘└─┘ └┘└──────────────┘   └─┘└─────────────┘└─
typ  ──────────┘└────────────────┘└─┘ └┘└──────────────┘└─┘└─┘└─────────────┘└─
doc  ──────────┘                  └─┘                      └─┘               └─
txt  ──────────┘                  └─┘                      └─┘               └─
par  ──────────┘                  └─┘                      └─┘               └─
pid  ──────────┘                  └─┘                      └─┘               
st   ────────────────────────────────────────────────────────┘└───────────────┘
3056    else
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘
3057      by rw [erase_append_right _ h₁, erase_append_right _ h₁, erase_append_right _ ha',
id              └────────────────┘   └┘  └────────────────┘   └┘  └────────────────┘   └─┘
src         └──┘└────────────────┘└─┘  └┘└────────────────┘└─┘  └┘└────────────────┘└─┘   └─
typ         └──┘└────────────────┘└─┘└┘└┘└────────────────┘└─┘└┘└┘└────────────────┘└─┘└─┘└─
doc         └──┘                  └─┘  └┘                  └─┘  └┘                  └─┘   └─
txt         └──┘                  └─┘  └┘                  └─┘  └┘                  └─┘   └─
par         └──┘                  └─┘  └┘                  └─┘  └┘                  └─┘   └─
pid           └┘                  └─┘  └┘                  └─┘  └┘                  └─┘   └─
st         └──────────────────────────┘└───────────────────────┘└────────────────────────┘└─
3058             erase_cons_tail _ ab, erase_cons_head]
id              └─────────────┘   └┘  └─────────────┘
src  ──────────┘└─────────────┘└─┘  └┘└─────────────┘└┘
typ  ──────────┘└─────────────┘└─┘└┘└┘└─────────────┘└┘
doc  ──────────┘               └─┘  └┘               └┘
txt  ──────────┘               └─┘  └┘               └┘
par  ──────────┘               └─┘  └┘               └┘
pid  ──────────┘               └─┘  └┘               
st   ──────────────────────────────┘└───────────────┘
3059  end
3060  else by simp only [erase_of_not_mem hb, erase_of_not_mem (mt mem_of_mem_erase hb)]
id                      └──────────────┘ └┘  └──────────────┘  └┘ └──────────────┘ └┘
src          └─────────┘└──────────────┘  └┘└──────────────┘ └┘└──────────────┘  └─┘
typ          └─────────┘└──────────────┘└┘└┘└──────────────┘ └┘└──────────────┘└┘└─┘
doc          └─────────┘                  └┘                                     └─┘
txt          └─────────┘                  └┘                                     └─┘
par          └─────────┘                  └┘                                     └─┘
pid              └──┘└┘                  └┘                                     └┘
st          └──────────────────────────────────────────────────────────────────────────┘
3061  else by simp only [erase_of_not_mem ha, erase_of_not_mem (mt mem_of_mem_erase ha)]
id                      └──────────────┘ └┘  └──────────────┘  └┘ └──────────────┘ └┘
src          └─────────┘└──────────────┘  └┘└──────────────┘ └┘└──────────────┘  └──
typ          └─────────┘└──────────────┘└┘└┘└──────────────┘ └┘└──────────────┘└┘└──
doc          └─────────┘                  └┘                                     └──
txt          └─────────┘                  └┘                                     └──
par          └─────────┘                  └┘                                     └──
pid              └──┘└┘                  └┘                                     └┘
st          └───────────────────────────────────────────────────────────────────────────
3062  
src  
typ  
doc  
txt  
par  
pid  
st   
3063  theorem map_erase [decidable_eq β] {f : α → β} (finj : injective f) {a : α}
id                      └──────────┘                     └───────┘        
src                     └──────────┘                        └───────┘
typ                     └──────────┘                     └───────┘        
3064    (l : list α) : map f (l.erase a) = (map f l).erase (f a) :=
id          └──┘     └─┘   └────┘     └─┘   └───┘    
src         └──┘      └─┘     └────┘      └─┘     └───┘
typ         └──┘     └─┘   └────┘     └─┘   └───┘    
3065  by rw [erase_eq_erasep, erase_eq_erasep, erasep_map]; congr;
id          └─────────────┘  └─────────────┘  └────────┘
src     └──┘└─────────────┘└┘└─────────────┘└┘└────────┘  └───┘
typ     └──┘└─────────────┘└┘└─────────────┘└┘└────────┘  └───┘
doc     └──┘               └┘               └┘          
txt     └──┘               └┘               └┘            └───┘
par     └──┘               └┘               └┘            └───┘
pid       └┘               └┘               └┘          
st     └──────────────────┘└───────────────┘└──────────┘└────────
3066     ext b; simp [finj.eq_iff]
src     └───┘  └────┘           └─
typ     └───┘  └────┘└─────────┘└─
doc     └───┘  └────┘           └─
txt     └───┘  └────┘           └─
par     └───┘  └────┘           └─
pid        └┘                 
st   ─────────────────────────────
3067  
src  
typ  
doc  
txt  
par  
pid  
st   
3068  theorem map_foldl_erase [decidable_eq β] {f : α → β} (finj : injective f) {l₁ l₂ : list α} :
id                            └──────────┘                     └───────┘            └──┘ 
src                           └──────────┘                        └───────┘             └──┘
typ                           └──────────┘                     └───────┘            └──┘ 
3069    map f (foldl list.erase l₁ l₂) = foldl (λ l a, l.erase (f a)) (map f l₁) l₂ :=
id     └─┘   └───┘ └────────┘ └┘ └┘   └───┘       └────┘       └─┘  └┘  └┘
src    └─┘    └───┘ └────────┘         └───┘          └────┘         └─┘
typ    └─┘   └───┘ └────────┘ └┘ └┘   └───┘       └────┘       └─┘  └┘  └┘
3070  by induction l₂ generalizing l₁; [refl,
id                └┘                  
src     └────────┘  └──────────────┘  └──┘
typ     └────────┘└┘└──────────────┘  └──┘
doc     └────────┘  └──────────────┘   └──┘
txt     └────────┘  └──────────────┘   └──┘
par     └────────┘  └──────────────┘   └──┘
pid                └─────────────┘
st     └─────────────────────────────────────
3071  simp only [foldl_cons, map_erase finj, *]]
id              └────────┘  └───────┘ └──┘
src  └─────────┘└────────┘└┘└───────┘    └──┘
typ  └─────────┘└────────┘└┘└───────┘└──┘└──┘
doc  └─────────┘          └┘             └──┘
txt  └─────────┘          └┘             └──┘
par  └─────────┘          └┘             └──┘
pid      └──┘└┘          └┘             └──┘
st   ─────────────────────────────────────────┘
3072  
3073  @[simp] theorem count_erase_self (a : α) : ∀ (s : list α), count a (list.erase s a) = pred (count a s)
id                                                   └──┘    └───┘   └────────┘     └──┘  └───┘  
src                                                    └──┘     └───┘    └────────┘       └──┘  └───┘
typ                                                  └──┘    └───┘   └────────┘     └──┘  └───┘  
doc    └──┘                                                     └───┘                            └───┘
3074  | [] := by simp
id     └┘
src    └┘       └───┘
typ    └┘       └───┘
doc             └───┘
txt             └───┘
par             └───┘
pid                 
st             └────┘
3075  | (h :: t) :=
id        └┘
src       └┘
typ       └┘
3076  begin
st   └─────
3077    rw erase_cons,
id        └────────┘
src    └─┘└────────┘
typ    └─┘└────────┘
doc    └─┘
txt    └─┘
par    └─┘
pid      
st   ──────────────┘└─
3078    by_cases p : h = a,
id                    
src    └───────┘ └─┘ 
typ    └───────┘ └─┘
doc    └───────┘ └─┘  
txt    └───────┘ └─┘  
par    └───────┘ └─┘  
pid             └─┘  
st   ───────────────────┘└─
3079    { rw [if_pos p, count_cons', if_pos p.symm], simp },
id           └────┘   └─────────┘  └────┘ └────┘
src      └──┘└────┘ └┘└─────────┘└┘└────┘└────┘  └───┘
typ      └──┘└────┘└┘└─────────┘└┘└────┘└────┘  └───┘
doc      └──┘       └┘           └┘              └───┘
txt      └──┘       └┘           └┘              └───┘
par      └──┘       └┘           └┘              └───┘
pid        └┘       └┘           └┘                  
st   ───┘└──────────┘└───────────┘└─────────────┘└──────┘└┘
3080    { rw [if_neg p, count_cons', count_cons', if_neg (λ x : a = h, p x.symm), count_erase_self],
id           └────┘   └─────────┘  └─────────┘  └────┘              └───┘   └──────────────┘
src      └──┘└────┘ └┘└─────────┘└┘└─────────┘└┘└────┘  └───┘   └┘  └───┘└─┘                
typ      └──┘└────┘└┘└─────────┘└┘└─────────┘└┘└────┘  └───┘└┘ └───┘└─┘└──────────────┘
doc      └──┘       └┘           └┘           └┘        └───┘   └┘       └─┘                
txt      └──┘       └┘           └┘           └┘        └───┘   └┘       └─┘                
par      └──┘       └┘           └┘           └┘        └───┘   └┘       └─┘                
pid        └┘       └┘           └┘           └┘        └───┘   └┘       └─┘                
st   ───────────────┘└───────────┘└───────────┘└──────────────────────────────┘└────────────────┘└──
3081      simp, }
src      └──┘
typ      └──┘
doc      └──┘
txt      └──┘
par      └──┘
st   ───────┘└───
3082  end
st   ──┘
3083  
3084  @[simp] theorem count_erase_of_ne {a b : α} (ab : a ≠ b) : ∀ (s : list α), count a (list.erase s b) = count a s
id                                                                └──┘    └───┘   └────────┘     └───┘  
src                                                                   └──┘     └───┘    └────────┘       └───┘
typ                                                               └──┘    └───┘   └────────┘     └───┘  
doc    └──┘                                                                     └───┘                      └───┘
3085  | [] := by simp
id     └┘
src    └┘       └───┘
typ    └┘       └───┘
doc             └───┘
txt             └───┘
par             └───┘
pid                 
st             └────┘
3086  | (x :: xs) :=
id        └┘
src       └┘
typ       └┘
3087  begin
st   └─────
3088    rw erase_cons,
id        └────────┘
src    └─┘└────────┘
typ    └─┘└────────┘
doc    └─┘
txt    └─┘
par    └─┘
pid      
st   ──────────────┘└─
3089    split_ifs with h,
src    └──────────────┘
typ    └──────────────┘
doc    └──────────────┘
txt    └──────────────┘
par    └──────────────┘
pid             └────┘
st   ─────────────────┘└─
3090    { rw [count_cons', h, if_neg ab], simp },
id           └─────────┘    └────┘ └┘
src      └──┘└─────────┘└┘ └┘└────┘    └───┘
typ      └──┘└─────────┘└┘└┘└────┘└┘  └───┘
doc      └──┘           └┘ └┘          └───┘
txt      └──┘           └┘ └┘          └───┘
par      └──┘           └┘ └┘          └───┘
pid        └┘           └┘ └┘              
st   ───┘└─────────────┘└─┘└─────────┘└──────┘└┘
3091    { rw [count_cons', count_cons', count_erase_of_ne] }
id           └─────────┘  └─────────┘  └───────────────┘
src      └──┘└─────────┘└┘└─────────┘└┘                 └┘
typ      └──┘└─────────┘└┘└─────────┘└┘└───────────────┘└┘
doc      └──┘           └┘           └┘                 └┘
txt      └──┘           └┘           └┘                 └┘
par      └──┘           └┘           └┘                 └┘
pid        └┘           └┘           └┘                 
st   ──────────────────┘└───────────┘└─────────────────┘└─
3092  end
st   ──┘
3093  
3094  end erase
3095  
3096  /- diff -/
3097  section diff
3098  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
3099  
3100  @[simp] theorem diff_nil (l : list α) : l.diff [] = l := rfl
id                                 └──┘     └───┘ └┘      └─┘
src                                └──┘       └───┘ └┘       └─┘
typ                                └──┘     └───┘ └┘      └─┘
doc    └──┘
3101  
3102  @[simp] theorem diff_cons (l₁ l₂ : list α) (a : α) : l₁.diff (a::l₂) = (l₁.erase a).diff l₂ :=
id                                      └──┘            └┘└───┘  └┘└┘    └┘└────┘  └──┘  └┘
src                                     └──┘                └───┘   └┘        └────┘   └──┘
typ                                     └──┘            └┘└───┘  └┘└┘    └┘└────┘  └──┘  └┘
doc    └──┘
3103  if h : a ∈ l₁ then by simp only [list.diff, if_pos h]
id   └┘       └┘                    └───────┘  └────┘ 
src  └┘                   └─────────┘└───────┘└┘└────┘ └┘
typ  └┘       └┘         └─────────┘└───────┘└┘└────┘└┘
doc                        └─────────┘         └┘       └┘
txt                        └─────────┘         └┘       └┘
par                        └─────────┘         └┘       └┘
pid                            └──┘└┘         └┘       
st                        └───────────────────────────────┘
3104  else by simp only [list.diff, if_neg h, erase_of_not_mem h]
id                      └───────┘  └────┘   └──────────────┘ 
src          └─────────┘└───────┘└┘└────┘ └┘└──────────────┘ └─
typ          └─────────┘└───────┘└┘└────┘└┘└──────────────┘└─
doc          └─────────┘         └┘       └┘                 └─
txt          └─────────┘         └┘       └┘                 └─
par          └─────────┘         └┘       └┘                 └─
pid              └──┘└┘         └┘       └┘                 
st          └────────────────────────────────────────────────────
3105  
src  
typ  
doc  
txt  
par  
pid  
st   
3106  @[simp] theorem nil_diff (l : list α) : [].diff l = [] :=
id                                 └──┘     └┘└──┘    └┘
src                                └──┘      └┘└──┘     └┘
typ                                └──┘     └┘└──┘    └┘
doc    └──┘
3107  by induction l; [refl, simp only [*, diff_cons, erase_of_not_mem (not_mem_nil _)]]
id                                      └───────┘  └──────────────┘  └─────────┘
src     └────────┘   └──┘  └────────────┘└───────┘└┘└──────────────┘ └─────────┘└──┘
typ     └────────┘  └──┘  └────────────┘└───────┘└┘└──────────────┘ └─────────┘└──┘
doc     └────────┘    └──┘  └────────────┘         └┘                            └──┘
txt     └────────┘    └──┘  └────────────┘         └┘                            └──┘
par     └────────┘    └──┘  └────────────┘         └┘                            └──┘
pid                            └──┘└───┘         └┘                            └──┘
st     └──────────────────────────────────────────────────────────────────────────────┘
3108  
3109  theorem diff_eq_foldl : ∀ (l₁ l₂ : list α), l₁.diff l₂ = foldl list.erase l₁ l₂
id                                     └──┘    └┘└───┘ └┘  └───┘ └────────┘ └┘ └┘
src                                     └──┘       └───┘     └───┘ └────────┘
typ                                    └──┘    └┘└───┘ └┘  └───┘ └────────┘ └┘ └┘
3110  | l₁ []      := rfl
id        └┘         └─┘
src       └┘         └─┘
typ       └┘         └─┘
3111  | l₁ (a::l₂) := (diff_cons l₁ l₂ a).trans (diff_eq_foldl _ _)
id     └┘  └┘└┘      └───────┘         └───┘   └───────────┘
src         └┘        └───────┘         └───┘
typ    └┘  └┘└┘      └───────┘         └───┘   └───────────┘
3112  
3113  @[simp] theorem diff_append (l₁ l₂ l₃ : list α) : l₁.diff (l₂ ++ l₃) = (l₁.diff l₂).diff l₃ :=
id                                           └──┘     └┘└───┘  └┘ └┘ └┘    └┘└───┘ └┘ └──┘  └┘
src                                          └──┘        └───┘     └┘         └───┘    └──┘
typ                                          └──┘     └┘└───┘  └┘ └┘ └┘    └┘└───┘ └┘ └──┘  └┘
doc    └──┘
3114  by simp only [diff_eq_foldl, foldl_append]
id                 └───────────┘  └──────────┘
src     └─────────┘└───────────┘└┘└──────────┘└─
typ     └─────────┘└───────────┘└┘└──────────┘└─
doc     └─────────┘             └┘            └─
txt     └─────────┘             └┘            └─
par     └─────────┘             └┘            └─
pid         └──┘└┘             └┘            
st     └────────────────────────────────────────
3115  
src  
typ  
doc  
txt  
par  
pid  
st   
3116  @[simp] theorem map_diff [decidable_eq β] {f : α → β} (finj : injective f) {l₁ l₂ : list α} :
id                             └──────────┘                     └───────┘            └──┘ 
src                            └──────────┘                        └───────┘             └──┘
typ                            └──────────┘                     └───────┘            └──┘ 
doc    └──┘
3117    map f (l₁.diff l₂) = (map f l₁).diff (map f l₂) :=
id     └─┘   └┘└───┘ └┘    └─┘  └┘ └──┘   └─┘  └┘
src    └─┘      └───┘       └─┘      └──┘   └─┘
typ    └─┘   └┘└───┘ └┘    └─┘  └┘ └──┘   └─┘  └┘
3118  by simp only [diff_eq_foldl, foldl_map, map_foldl_erase finj]
id                 └───────────┘  └───────┘  └─────────────┘ └──┘
src     └─────────┘└───────────┘└┘└───────┘└┘└─────────────┘    └─
typ     └─────────┘└───────────┘└┘└───────┘└┘└─────────────┘└──┘└─
doc     └─────────┘             └┘         └┘                   └─
txt     └─────────┘             └┘         └┘                   └─
par     └─────────┘             └┘         └┘                   └─
pid         └──┘└┘             └┘         └┘                   
st     └───────────────────────────────────────────────────────────
3119  
src  
typ  
doc  
txt  
par  
pid  
st   
3120  theorem diff_sublist : ∀ l₁ l₂ : list α, l₁.diff l₂ <+ l₁
id                            └┘      └──┘   └┘└───┘ └┘ └┘ └┘
src                                   └──┘      └───┘    └┘
typ                           └┘      └──┘   └┘└───┘ └┘ └┘ └┘
3121  | l₁ []      := sublist.refl _
id        └┘         └──────────┘
src       └┘         └──────────┘
typ       └┘         └──────────┘
3122  | l₁ (a::l₂) := calc l₁.diff (a :: l₂) = (l₁.erase a).diff l₂ : diff_cons _ _ _
id     └┘  └┘└┘            └───┘    └┘          └────┘   └──┘       └───────┘
src         └┘              └───┘    └┘          └────┘   └──┘       └───────┘
typ    └┘  └┘└┘            └───┘    └┘          └────┘   └──┘       └───────┘
3123    ... <+ l₁.erase a : diff_sublist _ _
id              └────┘     └──────────┘
src             └────┘
typ             └────┘     └──────────┘
3124    ... <+ l₁ : list.erase_sublist _ _
id                 └────────────────┘
src                └────────────────┘
typ                └────────────────┘
3125  
3126  theorem diff_subset (l₁ l₂ : list α) : l₁.diff l₂ ⊆ l₁ :=
id                                └──┘     └┘└───┘ └┘  └┘
src                               └──┘        └───┘    
typ                               └──┘     └┘└───┘ └┘  └┘
3127  subset_of_sublist $ diff_sublist _ _
id   └───────────────┘   └──────────┘
src  └───────────────┘   └──────────┘
typ  └───────────────┘   └──────────┘
3128  
3129  theorem mem_diff_of_mem {a : α} : ∀ {l₁ l₂ : list α}, a ∈ l₁ → a ∉ l₂ → a ∈ l₁.diff l₂
id                                              └──┘      └┘     └┘     └┘└───┘ └┘
src                                               └──┘                          └───┘
typ                                             └──┘      └┘     └┘     └┘└───┘ └┘
3130  | l₁ []      h₁ h₂ := h₁
id        └┘      └┘
src       └┘
typ       └┘      └┘
3131  | l₁ (b::l₂) h₁ h₂ := by rw diff_cons; exact
id          └┘                   └───────┘
src         └┘                └─┘└───────┘  └─────
typ         └┘                └─┘└───────┘  └─────
doc                           └─┘           └─────
txt                           └─┘           └─────
par                           └─┘           └─────
pid                                             
st                           └────────────────────
3132    mem_diff_of_mem ((mem_erase_of_ne (ne_of_not_mem_cons h₂)).2 h₁) (not_mem_of_not_mem_cons h₂)
id     └─────────────┘   └─────────────┘  └────────────────┘        └┘   └─────────────────────┘ └┘
src  ─┘                 └─────────────┘ └────────────────┘  └───┘  └┘ └─────────────────────┘  └─
typ  ─┘└─────────────┘  └─────────────┘ └────────────────┘  └───┘└┘└┘ └─────────────────────┘└┘└─
doc  ─┘                                                     └───┘  └┘                          └─
txt  ─┘                                                     └───┘  └┘                          └─
par  ─┘                                                     └───┘  └┘                          └─
pid  ─┘                                                     └───┘  └┘                          
st   ────────────────────────────────────────────────────────────────────────────────────────────────
3133  
src  
typ  
doc  
txt  
par  
pid  
st   
3134  theorem diff_sublist_of_sublist : ∀ {l₁ l₂ l₃: list α}, l₁ <+ l₂ → l₁.diff l₃ <+ l₂.diff l₃
id                                                 └──┘    └┘ └┘ └┘   └┘└───┘ └┘ └┘ └┘└───┘ └┘
src                                                 └──┘        └┘        └───┘    └┘   └───┘
typ                                                └──┘    └┘ └┘ └┘   └┘└───┘ └┘ └┘ └┘└───┘ └┘
3135  | l₁ l₂ [] h      := h
id           └┘ 
src          └┘
typ          └┘ 
3136  | l₁ l₂ (a::l₃) h := by simp only
id             └┘
src            └┘            └─────────
typ            └┘            └─────────
doc                          └─────────
txt                          └─────────
par                          └─────────
pid                              └──┘
st                          └──────────
3137    [diff_cons, diff_sublist_of_sublist (erase_sublist_erase _ h)]
id      └───────┘  └─────────────────────┘  └─────────────────┘   
src  ──┘└───────┘└┘                        └─────────────────┘└─┘ └──
typ  ──┘└───────┘└┘└─────────────────────┘ └─────────────────┘└─┘└──
doc  ──┘         └┘                                           └─┘ └──
txt  ──┘         └┘                                           └─┘ └──
par  ──┘         └┘                                           └─┘ └──
pid  ──┘         └┘                                           └─┘ └┘
st   ─────────────────────────────────────────────────────────────────
3138  
src  
typ  
doc  
txt  
par  
pid  
st   
3139  theorem erase_diff_erase_sublist_of_sublist {a : α} : ∀ {l₁ l₂ : list α},
id                                                                  └──┘ 
src                                                                   └──┘
typ                                                                 └──┘ 
3140    l₁ <+ l₂ → (l₂.erase a).diff (l₁.erase a) <+ l₂.diff l₁
id     └┘ └┘ └┘    └┘└────┘  └──┘   └┘└────┘   └┘ └┘└───┘ └┘
src       └┘         └────┘   └──┘     └────┘    └┘   └───┘
typ    └┘ └┘ └┘    └┘└────┘  └──┘   └┘└────┘   └┘ └┘└───┘ └┘
3141  | []      l₂ h := erase_sublist _ _
id     └┘              └───────────┘
src    └┘              └───────────┘
typ    └┘              └───────────┘
3142  | (b::l₁) l₂ h := if heq : b = a then by simp only [heq, erase_cons_head, diff_cons]
id      └┘            └┘                              └─┘  └─────────────┘  └───────┘
src      └┘            └┘                    └─────────┘└─┘└┘└─────────────┘└┘└───────┘└─
typ     └┘            └┘                   └─────────┘└─┘└┘└─────────────┘└┘└───────┘└─
doc                                           └─────────┘   └┘               └┘         └─
txt                                           └─────────┘   └┘               └┘         └─
par                                           └─────────┘   └┘               └┘         └─
pid                                               └──┘└┘   └┘               └┘         
st                                           └────────────────────────────────────────────
3143                    else by simpa only [erase_cons_head, erase_cons_tail _ heq, diff_cons, erase_comm a b l₂]
id                                         └─────────────┘  └─────────────┘   └─┘  └───────┘  └────────┘   └┘
src  ─────────────────┘        └──────────┘└─────────────┘└┘└─────────────┘└─┘└─┘└┘└───────┘└┘└────────┘    └─
typ  ─────────────────┘        └──────────┘└─────────────┘└┘└─────────────┘└─┘└─┘└┘└───────┘└┘└────────┘└┘└─
doc  ─────────────────┘        └──────────┘               └┘               └─┘   └┘         └┘              └─
txt  ─────────────────┘        └──────────┘               └┘               └─┘   └┘         └┘              └─
par  ─────────────────┘        └──────────┘               └┘               └─┘   └┘         └┘              └─
pid  ─────────────────┘             └──┘└┘               └┘               └─┘   └┘         └┘              
st   ─────────────────┘       └──────────────────────────────────────────────────────────────────────────────────
3144                    using erase_diff_erase_sublist_of_sublist (erase_sublist_erase b h)
id                           └─────────────────────────────────┘  └─────────────────┘  
src  ───────────────────────┘                                    └─────────────────┘  └┘
typ  ───────────────────────┘└─────────────────────────────────┘ └─────────────────┘└┘
doc  ───────────────────────┘                                                         └┘
txt  ───────────────────────┘                                                         └┘
par  ───────────────────────┘                                                         └┘
pid  ─────────────────┘└────┘                                                         
st   ─────────────────────────────────────────────────────────────────────────────────────┘
3145  using_well_founded wf_tacs
id                      └─────┘
src                     └─────┘
typ                     └─────┘
doc                     └─────┘
3146  
3147  end diff
3148  
3149  /- zip & unzip -/
3150  
3151  @[simp] theorem zip_cons_cons (a : α) (b : β) (l₁ : list α) (l₂ : list β) :
id                                                     └──┘         └──┘ 
src                                                      └──┘          └──┘
typ                                                    └──┘         └──┘ 
doc    └──┘
3152    zip (a :: l₁) (b :: l₂) = (a, b) :: zip l₁ l₂ := rfl
id     └─┘   └┘ └┘    └┘ └┘       └┘ └─┘ └┘ └┘    └─┘
src    └─┘    └┘        └┘            └┘ └─┘          └─┘
typ    └─┘   └┘ └┘    └┘ └┘       └┘ └─┘ └┘ └┘    └─┘
3153  
3154  @[simp] theorem zip_nil_left (l : list α) : zip ([] : list β) l = [] := rfl
id                                     └──┘     └─┘  └┘   └──┘     └┘    └─┘
src                                    └──┘      └─┘  └┘   └──┘       └┘    └─┘
typ                                    └──┘     └─┘  └┘   └──┘     └┘    └─┘
doc    └──┘
3155  
3156  @[simp] theorem zip_nil_right (l : list α) : zip l ([] : list β) = [] :=
id                                      └──┘     └─┘   └┘   └──┘    └┘
src                                     └──┘      └─┘    └┘   └──┘     └┘
typ                                     └──┘     └─┘   └┘   └──┘    └┘
doc    └──┘
3157  by cases l; refl
id            
src     └────┘   └────
typ     └────┘  └────
doc     └────┘   └────
txt     └────┘   └────
par     └────┘   └────
pid                 
st     └──────────────
3158  
src  
typ  
doc  
txt  
par  
pid  
st   
3159  @[simp] theorem zip_swap : ∀ (l₁ : list α) (l₂ : list β),
id                                     └──┘         └──┘ 
src                                     └──┘          └──┘
typ                                    └──┘         └──┘ 
doc    └──┘
3160    (zip l₁ l₂).map prod.swap = zip l₂ l₁
id      └─┘ └┘ └┘ └─┘  └───────┘  └─┘ └┘ └┘
src     └─┘       └─┘  └───────┘  └─┘
typ     └─┘ └┘ └┘ └─┘  └───────┘  └─┘ └┘ └┘
doc                    └───────┘
3161  | []      l₂      := (zip_nil_right _).symm
id     └┘                  └───────────┘   └──┘
src    └┘                  └───────────┘   └──┘
typ    └┘                  └───────────┘   └──┘
3162  | l₁      []      := by rw zip_nil_right; refl
id             └┘               └───────────┘
src            └┘            └─┘└───────────┘  └───┘
typ            └┘            └─┘└───────────┘  └───┘
doc                          └─┘               └───┘
txt                          └─┘               └───┘
par                          └─┘               └───┘
pid                                               
st                          └──────────────────────┘
3163  | (a::l₁) (b::l₂) := by simp only [zip_cons_cons, map_cons, zip_swap l₁ l₂, prod.swap_prod_mk]; split; refl
id       └┘      └┘                     └───────────┘  └──────┘  └──────┘ └┘ └┘  └───────────────┘
src      └┘      └┘          └─────────┘└───────────┘└┘└──────┘└┘            └┘└───────────────┘  └───┘  └────
typ      └┘      └┘          └─────────┘└───────────┘└┘└──────┘└┘└──────┘└┘└┘└┘└───────────────┘  └───┘  └────
doc                          └─────────┘             └┘        └┘            └┘                   └───┘  └────
txt                          └─────────┘             └┘        └┘            └┘                   └───┘  └────
par                          └─────────┘             └┘        └┘            └┘                   └───┘  └────
pid                              └──┘└┘             └┘        └┘            └┘                              
st                          └────────────────────────────────────────────────────────────────────────────────────
3164  
src  
typ  
doc  
txt  
par  
pid  
st   
3165  @[simp] theorem length_zip : ∀ (l₁ : list α) (l₂ : list β),
id                                       └──┘         └──┘ 
src                                       └──┘          └──┘
typ                                      └──┘         └──┘ 
doc    └──┘
3166     length (zip l₁ l₂) = min (length l₁) (length l₂)
id      └────┘  └─┘ └┘ └┘   └─┘  └────┘ └┘   └────┘ └┘
src     └────┘  └─┘         └─┘  └────┘      └────┘
typ     └────┘  └─┘ └┘ └┘   └─┘  └────┘ └┘   └────┘ └┘
3167  | []      l₂      := rfl
id     └┘                 └─┘
src    └┘                 └─┘
typ    └┘                 └─┘
3168  | l₁      []      := by simp only [length, zip_nil_right, min_zero]
id             └┘                       └────┘  └───────────┘  └──────┘
src            └┘            └─────────┘└────┘└┘└───────────┘└┘└──────┘└┘
typ            └┘            └─────────┘└────┘└┘└───────────┘└┘└──────┘└┘
doc                          └─────────┘      └┘             └┘        └┘
txt                          └─────────┘      └┘             └┘        └┘
par                          └─────────┘      └┘             └┘        └┘
pid                              └──┘└┘      └┘             └┘        
st                          └───────────────────────────────────────────┘
3169  | (a::l₁) (b::l₂) := by by simp only [length, zip_cons_cons, length_zip l₁ l₂, min_add_add_right]
id       └┘      └┘                        └────┘  └───────────┘  └────────┘ └┘ └┘  └───────────────┘
src      └┘      └┘             └─────────┘└────┘└┘└───────────┘└┘              └┘└───────────────┘└─
typ      └┘      └┘             └─────────┘└────┘└┘└───────────┘└┘└────────┘└┘└┘└┘└───────────────┘└─
doc                             └─────────┘      └┘             └┘              └┘                 └─
txt                             └─────────┘      └┘             └┘              └┘                 └─
par                             └─────────┘      └┘             └┘              └┘                 └─
pid                                 └──┘└┘      └┘             └┘              └┘                 
3170  
src  
typ  
doc  
txt  
par  
pid  
3171  theorem zip_append : ∀ {l₁ l₂ r₁ r₂ : list α} (h : length l₁ = length l₂),
id                                        └──┘        └────┘ └┘  └────┘ └┘
src                                        └──┘         └────┘     └────┘
typ                                       └──┘        └────┘ └┘  └────┘ └┘
3172     zip (l₁ ++ r₁) (l₂ ++ r₂) = zip l₁ l₂ ++ zip r₁ r₂
id      └─┘  └┘ └┘ └┘   └┘ └┘ └┘   └─┘ └┘ └┘ └┘ └─┘ └┘ └┘
src     └─┘     └┘         └┘      └─┘       └┘ └─┘
typ     └─┘  └┘ └┘ └┘   └┘ └┘ └┘   └─┘ └┘ └┘ └┘ └─┘ └┘ └┘
3173  | []      l₂      r₁ r₂ h := by simp only [eq_nil_of_length_eq_zero h.symm]; refl
id     └┘                                       └──────────────────────┘ └────┘
src    └┘                            └─────────┘└──────────────────────┘└────┘  └───┘
typ    └┘                            └─────────┘└──────────────────────┘└────┘  └───┘
doc                                  └─────────┘                                └───┘
txt                                  └─────────┘                                └───┘
par                                  └─────────┘                                └───┘
pid                                      └──┘└┘                                    
st                                  └─────────────────────────────────────────────────┘
3174  | l₁      []      r₁ r₂ h := by simp only [eq_nil_of_length_eq_zero h]; refl
id             └┘                               └──────────────────────┘ 
src            └┘                    └─────────┘└──────────────────────┘   └───┘
typ            └┘                    └─────────┘└──────────────────────┘  └───┘
doc                                  └─────────┘                           └───┘
txt                                  └─────────┘                           └───┘
par                                  └─────────┘                           └───┘
pid                                      └──┘└┘                               
st                                  └────────────────────────────────────────────┘
3175  | (a::l₁) (b::l₂) r₁ r₂ h := by simp only [cons_append, zip_cons_cons, zip_append (succ_inj h)]; split; refl
id       └┘      └┘                             └─────────┘  └───────────┘  └────────┘  └──────┘ 
src      └┘      └┘                  └─────────┘└─────────┘└┘└───────────┘└┘           └──────┘ └┘  └───┘  └────
typ      └┘      └┘                  └─────────┘└─────────┘└┘└───────────┘└┘└────────┘ └──────┘└┘  └───┘  └────
doc                                  └─────────┘           └┘             └┘                    └┘  └───┘  └────
txt                                  └─────────┘           └┘             └┘                    └┘  └───┘  └────
par                                  └─────────┘           └┘             └┘                    └┘  └───┘  └────
pid                                      └──┘└┘           └┘             └┘                    └┘             
st                                  └─────────────────────────────────────────────────────────────────────────────
3176  
src  
typ  
doc  
txt  
par  
pid  
st   
3177  theorem zip_map (f : α → γ) (g : β → δ) : ∀ (l₁ : list α) (l₂ : list β),
id                                                └──┘         └──┘ 
src                                                    └──┘          └──┘
typ                                               └──┘         └──┘ 
3178     zip (l₁.map f) (l₂.map g) = (zip l₁ l₂).map (prod.map f g)
id      └─┘  └┘└──┘    └┘└──┘     └─┘ └┘ └┘ └─┘   └──────┘  
src     └─┘    └──┘       └──┘      └─┘       └─┘   └──────┘
typ     └─┘  └┘└──┘    └┘└──┘     └─┘ └┘ └┘ └─┘   └──────┘  
3179  | []      l₂      := rfl
id     └┘                 └─┘
src    └┘                 └─┘
typ    └┘                 └─┘
3180  | l₁      []      := by simp only [map, zip_nil_right]
id             └┘                       └─┘  └───────────┘
src            └┘            └─────────┘└─┘└┘└───────────┘└┘
typ            └┘            └─────────┘└─┘└┘└───────────┘└┘
doc                          └─────────┘   └┘             └┘
txt                          └─────────┘   └┘             └┘
par                          └─────────┘   └┘             └┘
pid                              └──┘└┘   └┘             
st                          └──────────────────────────────┘
3181  | (a::l₁) (b::l₂) := by simp only [map, zip_cons_cons, zip_map l₁ l₂, prod.map]; split; refl
id       └┘      └┘                     └─┘  └───────────┘  └─────┘ └┘ └┘  └──────┘
src      └┘      └┘          └─────────┘└─┘└┘└───────────┘└┘           └┘└──────┘  └───┘  └────
typ      └┘      └┘          └─────────┘└─┘└┘└───────────┘└┘└─────┘└┘└┘└┘└──────┘  └───┘  └────
doc                          └─────────┘   └┘             └┘           └┘          └───┘  └────
txt                          └─────────┘   └┘             └┘           └┘          └───┘  └────
par                          └─────────┘   └┘             └┘           └┘          └───┘  └────
pid                              └──┘└┘   └┘             └┘           └┘                     
st                          └─────────────────────────────────────────────────────────────────────
3182  
src  
typ  
doc  
txt  
par  
pid  
st   
3183  theorem zip_map_left (f : α → γ) (l₁ : list α) (l₂ : list β) :
id                                        └──┘         └──┘ 
src                                         └──┘          └──┘
typ                                       └──┘         └──┘ 
3184     zip (l₁.map f) l₂ = (zip l₁ l₂).map (prod.map f id) :=
id      └─┘  └┘└──┘   └┘   └─┘ └┘ └┘ └─┘   └──────┘  └┘
src     └─┘    └──┘         └─┘       └─┘   └──────┘   └┘
typ     └─┘  └┘└──┘   └┘   └─┘ └┘ └┘ └─┘   └──────┘  └┘
3185  by rw [← zip_map, map_id]
id            └─────┘  └────┘
src     └────┘└─────┘└┘└────┘└─
typ     └────┘└─────┘└┘└────┘└─
doc     └────┘       └┘      └─
txt     └────┘       └┘      └─
par     └────┘       └┘      └─
pid       └──┘       └┘      
st     └────────────┘└──────┘
3186  
src  
typ  
doc  
txt  
par  
pid  
st   
3187  theorem zip_map_right (f : β → γ) (l₁ : list α) (l₂ : list β) :
id                                         └──┘         └──┘ 
src                                          └──┘          └──┘
typ                                        └──┘         └──┘ 
3188     zip l₁ (l₂.map f) = (zip l₁ l₂).map (prod.map id f) :=
id      └─┘ └┘  └┘└──┘     └─┘ └┘ └┘ └─┘   └──────┘ └┘ 
src     └─┘       └──┘      └─┘       └─┘   └──────┘ └┘
typ     └─┘ └┘  └┘└──┘     └─┘ └┘ └┘ └─┘   └──────┘ └┘ 
3189  by rw [← zip_map, map_id]
id            └─────┘  └────┘
src     └────┘└─────┘└┘└────┘└─
typ     └────┘└─────┘└┘└────┘└─
doc     └────┘       └┘      └─
txt     └────┘       └┘      └─
par     └────┘       └┘      └─
pid       └──┘       └┘      
st     └────────────┘└──────┘
3190  
src  
typ  
doc  
txt  
par  
pid  
st   
3191  theorem zip_map' (f : α → β) (g : α → γ) : ∀ (l : list α),
id                                                └──┘ 
src                                                    └──┘
typ                                               └──┘ 
3192     zip (l.map f) (l.map g) = l.map (λ a, (f a, g a))
id      └─┘  └──┘    └──┘    └──┘          
src     └─┘   └──┘      └──┘      └──┘       
typ     └─┘  └──┘    └──┘    └──┘          
3193  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
3194  | (a::l) := by simp only [map, zip_cons_cons, zip_map' l]; split; refl
id       └┘                    └─┘  └───────────┘  └──────┘ 
src      └┘         └─────────┘└─┘└┘└───────────┘└┘           └───┘  └────
typ      └┘         └─────────┘└─┘└┘└───────────┘└┘└──────┘  └───┘  └────
doc                 └─────────┘   └┘             └┘           └───┘  └────
txt                 └─────────┘   └┘             └┘           └───┘  └────
par                 └─────────┘   └┘             └┘           └───┘  └────
pid                     └──┘└┘   └┘             └┘                      
st                 └────────────────────────────────────────────────────────
3195  
src  
typ  
doc  
txt  
par  
pid  
st   
3196  theorem mem_zip {a b} : ∀ {l₁ : list α} {l₂ : list β},
id                                  └──┘         └──┘ 
src                                  └──┘          └──┘
typ                                 └──┘         └──┘ 
3197     (a, b) ∈ zip l₁ l₂ → a ∈ l₁ ∧ b ∈ l₂
id           └─┘ └┘ └┘     └┘    └┘
src            └─┘                  
typ          └─┘ └┘ └┘     └┘    └┘
3198  | (_::l₁) (_::l₂) (or.inl rfl) := ⟨or.inl rfl, or.inl rfl⟩
id       └┘      └┘     └────┘ └─┘      └────┘ └─┘  └────┘ └─┘
src      └┘      └┘     └────┘ └─┘      └────┘ └─┘  └────┘ └─┘
typ      └┘      └┘     └────┘ └─┘      └────┘ └─┘  └────┘ └─┘
3199  | (a'::l₁) (b'::l₂) (or.inr h) := by split; simp only [mem_cons_iff, or_true, mem_zip h]
id        └┘       └┘     └────┘                            └──────────┘  └─────┘  └─────┘ 
src       └┘       └┘     └────┘          └───┘  └─────────┘└──────────┘└┘└─────┘└┘        └─
typ       └┘       └┘     └────┘          └───┘  └─────────┘└──────────┘└┘└─────┘└┘└─────┘└─
doc                                       └───┘  └─────────┘            └┘       └┘        └─
txt                                       └───┘  └─────────┘            └┘       └┘        └─
par                                       └───┘  └─────────┘            └┘       └┘        └─
pid                                                  └──┘└┘            └┘       └┘        
st                                       └────────────────────────────────────────────────────
3200  
src  
typ  
doc  
txt  
par  
pid  
st   
3201  @[simp] theorem unzip_nil : unzip (@nil (α × β)) = ([], []) := rfl
id                               └───┘   └─┘        └┘  └┘     └─┘
src                              └───┘   └─┘          └┘  └┘     └─┘
typ                              └───┘   └─┘        └┘  └┘     └─┘
doc    └──┘
3202  
3203  @[simp] theorem unzip_cons (a : α) (b : β) (l : list (α × β)) :
id                                                 └──┘    
src                                                  └──┘    
typ                                                └──┘    
doc    └──┘
3204     unzip ((a, b) :: l) = (a :: (unzip l).1, b :: (unzip l).2) :=
id      └───┘      └┘     └┘  └───┘      └┘  └───┘  
src     └───┘        └┘       └┘  └───┘        └┘  └───┘   
typ     └───┘      └┘     └┘  └───┘      └┘  └───┘  
3205  by rw unzip; cases unzip l; refl
id         └───┘        └───┘ 
src     └─┘└───┘  └────┘└───┘   └────
typ     └─┘└───┘  └────┘└───┘  └────
doc     └─┘       └────┘        └────
txt     └─┘       └────┘        └────
par     └─┘       └────┘        └────
pid                               
st     └──────────────────────────────
3206  
src  
typ  
doc  
txt  
par  
pid  
st   
3207  theorem unzip_eq_map : ∀ (l : list (α × β)), unzip l = (l.map prod.fst, l.map prod.snd)
id                                └──┘        └───┘   └──┘ └──────┘  └──┘ └──────┘
src                                └──┘          └───┘     └──┘ └──────┘   └──┘ └──────┘
typ                               └──┘        └───┘   └──┘ └──────┘  └──┘ └──────┘
3208  | []            := rfl
id     └┘               └─┘
src    └┘               └─┘
typ    └┘               └─┘
3209  | ((a, b) :: l) := by simp only [unzip_cons, map_cons, unzip_eq_map l]
id            └┘                     └────────┘  └──────┘  └──────────┘ 
src           └┘          └─────────┘└────────┘└┘└──────┘└┘             └─
typ           └┘          └─────────┘└────────┘└┘└──────┘└┘└──────────┘└─
doc                        └─────────┘          └┘        └┘             └─
txt                        └─────────┘          └┘        └┘             └─
par                        └─────────┘          └┘        └┘             └─
pid                            └──┘└┘          └┘        └┘             
st                        └─────────────────────────────────────────────────
3210  
src  
typ  
doc  
txt  
par  
pid  
st   
3211  theorem unzip_left (l : list (α × β)) : (unzip l).1 = l.map prod.fst :=
id                           └──┘          └───┘     └──┘ └──────┘
src                          └──┘            └───┘       └──┘ └──────┘
typ                          └──┘          └───┘     └──┘ └──────┘
3212  by simp only [unzip_eq_map]
id                 └──────────┘
src     └─────────┘└──────────┘└─
typ     └─────────┘└──────────┘└─
doc     └─────────┘            └─
txt     └─────────┘            └─
par     └─────────┘            └─
pid         └──┘└┘            
st     └─────────────────────────
3213  
src  
typ  
doc  
txt  
par  
pid  
st   
3214  theorem unzip_right (l : list (α × β)) : (unzip l).2 = l.map prod.snd :=
id                            └──┘          └───┘     └──┘ └──────┘
src                           └──┘            └───┘       └──┘ └──────┘
typ                           └──┘          └───┘     └──┘ └──────┘
3215  by simp only [unzip_eq_map]
id                 └──────────┘
src     └─────────┘└──────────┘└─
typ     └─────────┘└──────────┘└─
doc     └─────────┘            └─
txt     └─────────┘            └─
par     └─────────┘            └─
pid         └──┘└┘            
st     └─────────────────────────
3216  
src  
typ  
doc  
txt  
par  
pid  
st   
3217  theorem unzip_swap (l : list (α × β)) : unzip (l.map prod.swap) = (unzip l).swap :=
id                           └──┘         └───┘  └──┘ └───────┘    └───┘  └──┘
src                          └──┘           └───┘   └──┘ └───────┘    └───┘   └──┘
typ                          └──┘         └───┘  └──┘ └───────┘    └───┘  └──┘
doc                                                       └───────┘             └──┘
3218  by simp only [unzip_eq_map, map_map]; split; refl
id                 └──────────┘  └─────┘
src     └─────────┘└──────────┘└┘└─────┘  └───┘  └────
typ     └─────────┘└──────────┘└┘└─────┘  └───┘  └────
doc     └─────────┘            └┘         └───┘  └────
txt     └─────────┘            └┘         └───┘  └────
par     └─────────┘            └┘         └───┘  └────
pid         └──┘└┘            └┘                    
st     └───────────────────────────────────────────────
3219  
src  
typ  
doc  
txt  
par  
pid  
st   
3220  theorem zip_unzip : ∀ (l : list (α × β)), zip (unzip l).1 (unzip l).2 = l
id                             └──┘        └─┘  └───┘     └───┘     
src                             └──┘          └─┘  └───┘      └───┘     
typ                            └──┘        └─┘  └───┘     └───┘     
3221  | []            := rfl
id     └┘               └─┘
src    └┘               └─┘
typ    └┘               └─┘
3222  | ((a, b) :: l) := by simp only [unzip_cons, zip_cons_cons, zip_unzip l]; split; refl
id            └┘                     └────────┘  └───────────┘  └───────┘ 
src           └┘          └─────────┘└────────┘└┘└───────────┘└┘            └───┘  └────
typ           └┘          └─────────┘└────────┘└┘└───────────┘└┘└───────┘  └───┘  └────
doc                        └─────────┘          └┘             └┘            └───┘  └────
txt                        └─────────┘          └┘             └┘            └───┘  └────
par                        └─────────┘          └┘             └┘            └───┘  └────
pid                            └──┘└┘          └┘             └┘                       
st                        └────────────────────────────────────────────────────────────────
3223  
src  
typ  
doc  
txt  
par  
pid  
st   
3224  theorem unzip_zip_left : ∀ {l₁ : list α} {l₂ : list β}, length l₁ ≤ length l₂ →
id                                   └──┘         └──┘    └────┘ └┘  └────┘ └┘
src                                   └──┘          └──┘     └────┘     └────┘
typ                                  └──┘         └──┘    └────┘ └┘  └────┘ └┘
3225    (unzip (zip l₁ l₂)).1 = l₁
id      └───┘  └─┘ └┘ └┘     └┘
src     └───┘  └─┘          
typ     └───┘  └─┘ └┘ └┘     └┘
3226  | []      l₂      h := rfl
id     └┘                   └─┘
src    └┘                   └─┘
typ    └┘                   └─┘
3227  | l₁      []      h := by rw eq_nil_of_length_eq_zero (eq_zero_of_le_zero h); refl
id             └┘                 └──────────────────────┘  └────────────────┘ 
src            └┘              └─┘└──────────────────────┘ └────────────────┘   └───┘
typ            └┘              └─┘└──────────────────────┘ └────────────────┘  └───┘
doc                            └─┘                                              └───┘
txt                            └─┘                                              └───┘
par                            └─┘                                              └───┘
pid                                                                                
st                            └────────────────────────────────────────────────────────┘
3228  | (a::l₁) (b::l₂) h := by simp only [zip_cons_cons, unzip_cons, unzip_zip_left (le_of_succ_le_succ h)]; split; refl
id       └┘      └┘                       └───────────┘  └────────┘  └────────────┘  └────────────────┘ 
src      └┘      └┘            └─────────┘└───────────┘└┘└────────┘└┘               └────────────────┘ └┘  └───┘  └────
typ      └┘      └┘            └─────────┘└───────────┘└┘└────────┘└┘└────────────┘ └────────────────┘└┘  └───┘  └────
doc                            └─────────┘             └┘          └┘                                  └┘  └───┘  └────
txt                            └─────────┘             └┘          └┘                                  └┘  └───┘  └────
par                            └─────────┘             └┘          └┘                                  └┘  └───┘  └────
pid                                └──┘└┘             └┘          └┘                                  └┘             
st                            └──────────────────────────────────────────────────────────────────────────────────────────
3229  
src  
typ  
doc  
txt  
par  
pid  
st   
3230  theorem unzip_zip_right {l₁ : list α} {l₂ : list β} (h : length l₂ ≤ length l₁) :
id                                 └──┘         └──┘        └────┘ └┘  └────┘ └┘
src                                └──┘          └──┘         └────┘     └────┘
typ                                └──┘         └──┘        └────┘ └┘  └────┘ └┘
3231    (unzip (zip l₁ l₂)).2 = l₂ :=
id      └───┘  └─┘ └┘ └┘     └┘
src     └───┘  └─┘          
typ     └───┘  └─┘ └┘ └┘     └┘
3232  by rw [← zip_swap, unzip_swap]; exact unzip_zip_left h
id            └──────┘  └────────┘         └────────────┘ 
src     └────┘└──────┘└┘└────────┘  └────┘└────────────┘ 
typ     └────┘└──────┘└┘└────────┘  └────┘└────────────┘
doc     └────┘        └┘            └────┘               
txt     └────┘        └┘            └────┘               
par     └────┘        └┘            └────┘               
pid       └──┘        └┘                                
st     └─────────────┘└──────────┘└────────────────────────
3233  
src  
typ  
doc  
txt  
par  
pid  
st   
3234  theorem unzip_zip {l₁ : list α} {l₂ : list β} (h : length l₁ = length l₂) :
id                           └──┘         └──┘        └────┘ └┘  └────┘ └┘
src                          └──┘          └──┘         └────┘     └────┘
typ                          └──┘         └──┘        └────┘ └┘  └────┘ └┘
3235    unzip (zip l₁ l₂) = (l₁, l₂) :=
id     └───┘  └─┘ └┘ └┘   └┘  └┘
src    └───┘  └─┘         
typ    └───┘  └─┘ └┘ └┘   └┘  └┘
3236  by rw [← @prod.mk.eta _ _ (unzip (zip l₁ l₂)),
id             └─────────┘      └───┘  └─┘ └┘ └┘
src     └────┘ └─────────┘└───┘ └───┘ └─┘    └───
typ     └────┘ └─────────┘└───┘ └───┘ └─┘└┘└┘└───
doc     └────┘            └───┘              └───
txt     └────┘            └───┘              └───
par     └────┘            └───┘              └───
pid       └──┘            └───┘              └───
st     └─────────────────────────────────────────┘└─
3237    unzip_zip_left (le_of_eq h), unzip_zip_right (ge_of_eq h)]
id     └────────────┘  └──────┘    └─────────────┘  └──────┘ 
src  ─┘└────────────┘ └──────┘ └─┘└─────────────┘ └──────┘ └──
typ  ─┘└────────────┘ └──────┘└─┘└─────────────┘ └──────┘└──
doc  ─┘                        └─┘                         └──
txt  ─┘                        └─┘                         └──
par  ─┘                        └─┘                         └──
pid  ─┘                        └─┘                         └┘
st   ────────────────────────────┘└────────────────────────────┘
3238  
src  
typ  
doc  
txt  
par  
pid  
st   
3239  @[simp] theorem length_revzip (l : list α) : length (revzip l) = length l :=
id                                      └──┘     └────┘  └────┘    └────┘ 
src                                     └──┘      └────┘  └────┘     └────┘
typ                                     └──┘     └────┘  └────┘    └────┘ 
doc    └──┘
3240  by simp only [revzip, length_zip, length_reverse, min_self]
id                 └────┘  └────────┘  └────────────┘  └──────┘
src     └─────────┘└────┘└┘└────────┘└┘└────────────┘└┘└──────┘└─
typ     └─────────┘└────┘└┘└────────┘└┘└────────────┘└┘└──────┘└─
doc     └─────────┘      └┘          └┘              └┘        └─
txt     └─────────┘      └┘          └┘              └┘        └─
par     └─────────┘      └┘          └┘              └┘        └─
pid         └──┘└┘      └┘          └┘              └┘        
st     └─────────────────────────────────────────────────────────
3241  
src  
typ  
doc  
txt  
par  
pid  
st   
3242  @[simp] theorem unzip_revzip (l : list α) : (revzip l).unzip = (l, l.reverse) :=
id                                     └──┘      └────┘  └───┘     └──────┘
src                                    └──┘       └────┘   └───┘       └──────┘
typ                                    └──┘      └────┘  └───┘     └──────┘
doc    └──┘
3243  unzip_zip (length_reverse l).symm
id   └───────┘  └────────────┘  └──┘
src  └───────┘  └────────────┘   └──┘
typ  └───────┘  └────────────┘  └──┘
3244  
3245  @[simp] theorem revzip_map_fst (l : list α) : (revzip l).map prod.fst = l :=
id                                       └──┘      └────┘  └─┘  └──────┘  
src                                      └──┘       └────┘   └─┘  └──────┘ 
typ                                      └──┘      └────┘  └─┘  └──────┘  
doc    └──┘
3246  by rw [← unzip_left, unzip_revzip]
id            └────────┘  └──────────┘
src     └────┘└────────┘└┘└──────────┘└─
typ     └────┘└────────┘└┘└──────────┘└─
doc     └────┘          └┘            └─
txt     └────┘          └┘            └─
par     └────┘          └┘            └─
pid       └──┘          └┘            
st     └───────────────┘└────────────┘
3247  
src  
typ  
doc  
txt  
par  
pid  
st   
3248  @[simp] theorem revzip_map_snd (l : list α) : (revzip l).map prod.snd = l.reverse :=
id                                       └──┘      └────┘  └─┘  └──────┘  └──────┘
src                                      └──┘       └────┘   └─┘  └──────┘   └──────┘
typ                                      └──┘      └────┘  └─┘  └──────┘  └──────┘
doc    └──┘
3249  by rw [← unzip_right, unzip_revzip]
id            └─────────┘  └──────────┘
src     └────┘└─────────┘└┘└──────────┘└─
typ     └────┘└─────────┘└┘└──────────┘└─
doc     └────┘           └┘            └─
txt     └────┘           └┘            └─
par     └────┘           └┘            └─
pid       └──┘           └┘            
st     └────────────────┘└────────────┘
3250  
src  
typ  
doc  
txt  
par  
pid  
st   
3251  theorem reverse_revzip (l : list α) : reverse l.revzip = revzip l.reverse :=
id                               └──┘     └─────┘ └─────┘  └────┘ └──────┘
src                              └──┘      └─────┘  └─────┘  └────┘  └──────┘
typ                              └──┘     └─────┘ └─────┘  └────┘ └──────┘
3252  by rw [← zip_unzip.{u u} (revzip l).reverse, unzip_eq_map]; simp; simp [revzip]
id            └───────┘        └────┘            └──────────┘               └────┘
src     └────┘└───────┘└─────┘ └────┘ └─────────┘└──────────┘  └──┘  └────┘└────┘└─
typ     └────┘└───────┘└─────┘ └────┘└─────────┘└──────────┘  └──┘  └────┘└────┘└─
doc     └────┘         └─────┘        └─────────┘              └──┘  └────┘      └─
txt     └────┘         └─────┘        └─────────┘              └──┘  └────┘      └─
par     └────┘         └─────┘        └─────────┘              └──┘  └────┘      └─
pid       └──┘         └─────┘        └─────────┘                              
st     └──────────────────────────────────────┘└─────────────┘└─────────────────────
3253  
src  
typ  
doc  
txt  
par  
pid  
st   
3254  theorem revzip_swap (l : list α) : (revzip l).map prod.swap = revzip l.reverse :=
id                            └──┘      └────┘  └─┘  └───────┘  └────┘ └──────┘
src                           └──┘       └────┘   └─┘  └───────┘  └────┘  └──────┘
typ                           └──┘      └────┘  └─┘  └───────┘  └────┘ └──────┘
doc                                                    └───────┘
3255  by simp [revzip]
id            └────┘
src     └────┘└────┘└─
typ     └────┘└────┘└─
doc     └────┘      └─
txt     └────┘      └─
par     └────┘      └─
pid               
st     └──────────────
3256  
src  
typ  
doc  
txt  
par  
pid  
st   
3257  /- enum -/
src  ───────────
typ  ───────────
doc  ───────────
txt  ───────────
par  ───────────
pid  ───────────
st   ───────────
3258  
src  
typ  
doc  
txt  
par  
pid  
st   
3259  theorem length_enum_from : ∀ n (l : list α), length (enum_from n l) = length l
id                                      └──┘    └────┘  └───────┘     └────┘ 
src                                      └──┘     └────┘  └───────┘       └────┘
typ                                     └──┘    └────┘  └───────┘     └────┘ 
3260  | n []     := rfl
id       └┘        └─┘
src      └┘        └─┘
typ      └┘        └─┘
3261  | n (a::l) := congr_arg nat.succ (length_enum_from _ _)
id         └┘      └───────┘ └──────┘  └──────────────┘
src        └┘      └───────┘ └──────┘
typ        └┘      └───────┘ └──────┘  └──────────────┘
3262  
3263  theorem length_enum : ∀ (l : list α), length (enum l) = length l := length_enum_from _
id                                └──┘    └────┘  └──┘    └────┘     └──────────────┘
src                               └──┘     └────┘  └──┘     └────┘      └──────────────┘
typ                               └──┘    └────┘  └──┘    └────┘     └──────────────┘
3264  
3265  @[simp] theorem enum_from_nth : ∀ n (l : list α) m,
id                                           └──┘   
src                                           └──┘
typ                                          └──┘   
doc    └──┘
3266    nth (enum_from n l) m = (λ a, (n + m, a)) <$> nth l m
id     └─┘  └───────┘                  └─┘ └─┘  
src    └─┘  └───────┘                         └─┘ └─┘
typ    └─┘  └───────┘                  └─┘ └─┘  
3267  | n []       m     := rfl
id       └┘                └─┘
src      └┘                └─┘
typ      └┘                └─┘
3268  | n (a :: l) 0     := rfl
id          └┘             └─┘
src         └┘             └─┘
typ         └┘             └─┘
3269  | n (a :: l) (m+1) := (enum_from_nth (n+1) l m).trans $
id         └┘           └───────────┘          └───┘
src         └┘                                    └───┘
typ        └┘           └───────────┘          └───┘
3270    by rw [add_right_comm]; refl
id            └────────────┘
src       └──┘└────────────┘  └────
typ       └──┘└────────────┘  └────
doc       └──┘                └────
txt       └──┘                └────
par       └──┘                └────
pid         └┘                    
st       └─────────────────┘└──────
3271  
src  
typ  
doc  
txt  
par  
pid  
st   
3272  @[simp] theorem enum_nth : ∀ (l : list α) n,
id                                     └──┘   
src                                    └──┘
typ                                    └──┘   
doc    └──┘
3273    nth (enum l) n = (λ a, (n, a)) <$> nth l n :=
id     └─┘  └──┘               └─┘ └─┘  
src    └─┘  └──┘                    └─┘ └─┘
typ    └─┘  └──┘               └─┘ └─┘  
3274  by simp only [enum, enum_from_nth, zero_add]; intros; refl
id                 └──┘  └───────────┘  └──────┘
src     └─────────┘└──┘└┘└───────────┘└┘└──────┘  └────┘  └────
typ     └─────────┘└──┘└┘└───────────┘└┘└──────┘  └────┘  └────
doc     └─────────┘    └┘             └┘          └────┘  └────
txt     └─────────┘    └┘             └┘          └────┘  └────
par     └─────────┘    └┘             └┘          └────┘  └────
pid         └──┘└┘    └┘             └┘                      
st     └────────────────────────────────────────────────────────
3275  
src  
typ  
doc  
txt  
par  
pid  
st   
3276  @[simp] theorem enum_from_map_snd : ∀ n (l : list α),
id                                               └──┘ 
src                                               └──┘
typ                                              └──┘ 
doc    └──┘
3277    map prod.snd (enum_from n l) = l
id     └─┘ └──────┘  └───────┘     
src    └─┘ └──────┘  └───────┘      
typ    └─┘ └──────┘  └───────┘     
3278  | n []       := rfl
id       └┘          └─┘
src      └┘          └─┘
typ      └┘          └─┘
3279  | n (a :: l) := congr_arg (cons _) (enum_from_map_snd _ _)
id          └┘       └───────┘  └──┘     └───────────────┘
src         └┘       └───────┘  └──┘
typ         └┘       └───────┘  └──┘     └───────────────┘
3280  
3281  @[simp] theorem enum_map_snd : ∀ (l : list α),
id                                         └──┘ 
src                                        └──┘
typ                                        └──┘ 
doc    └──┘
3282    map prod.snd (enum l) = l := enum_from_map_snd _
id     └─┘ └──────┘  └──┘        └───────────────┘
src    └─┘ └──────┘  └──┘          └───────────────┘
typ    └─┘ └──────┘  └──┘        └───────────────┘
3283  
3284  theorem mem_enum_from {x : α} {i : ℕ} : Π {j : ℕ} (xs : list α), (i, x) ∈ xs.enum_from j → j ≤ i ∧ i < j + xs.length ∧ x ∈ xs
id                                                       └──┘         └┘└────────┘            └┘└─────┘    └┘
src                                                        └──┘              └────────┘                   └─────┘    
typ                                                      └──┘         └┘└────────┘            └┘└─────┘    └┘
3285  | j [] := by simp [enum_from]
id       └┘             └───────┘
src      └┘       └────┘└───────┘└┘
typ      └┘       └────┘└───────┘└┘
doc               └────┘         └┘
txt               └────┘         └┘
par               └────┘         └┘
pid                            
st               └────────────────┘
3286  | j (y :: ys) := by { simp [enum_from,mem_enum_from ys],
id          └┘                   └───────┘ └───────────┘ └┘
src         └┘             └────┘└───────┘               
typ         └┘             └────┘└───────┘└───────────┘└┘
doc                        └────┘                        
txt                        └────┘                        
par                        └────┘                        
pid                                                    
st                      └──────────────────────────────────┘└─
3287                        rintro (h|h),
src                        └──────────┘
typ                        └──────────┘
doc                        └──────────┘
txt                        └──────────┘
par                        └──────────┘
pid                              └────┘
st   ─────────────────────────────────┘└─
3288                        { refine ⟨le_of_eq h.1.symm,h.1 ▸ _,or.inl h.2⟩,
id                                   └──────┘                 └────┘ 
src                          └─────┘ └──────┘ └──────┘ └─┘└─┘└────┘ └─┘
typ                          └─────┘ └──────┘ └──────┘ └─┘└─┘└────┘└─┘
doc                          └─────┘          └──────┘ └─┘ └─┘       └─┘
txt                          └─────┘          └──────┘ └─┘ └─┘       └─┘
par                          └─────┘          └──────┘ └─┘ └─┘       └─┘
pid                                          └──────┘ └─┘ └─┘       └─┘
st   ───────────────────────┘└───────────────────────────────────────────┘└─
3289                          apply lt_of_lt_of_le (nat.lt_add_of_pos_right zero_lt_one),
id                                 └────────────┘  └─────────────────────┘ └─────────┘
src                          └────┘└────────────┘ └─────────────────────┘└─────────┘
typ                          └────┘└────────────┘ └─────────────────────┘└─────────┘
doc                          └────┘                                                 
txt                          └────┘                                                 
par                          └────┘                                                 
pid                                                                                
st   ─────────────────────────────────────────────────────────────────────────────────┘└─
3290                          apply nat.add_le_add_left, apply nat.le_add_right },
id                                 └─────────────────┘        └──────────────┘
src                          └────┘└─────────────────┘  └────┘└──────────────┘
typ                          └────┘└─────────────────┘  └────┘└──────────────┘
doc                          └────┘                     └────┘                
txt                          └────┘                     └────┘                
par                          └────┘                     └────┘                
pid                                                                         
st   ────────────────────────────────────────────────┘└───────────────────────┘└┘
3291                        { replace h := mem_enum_from _ h,
id                                        └───────────┘   
src                          └───────────┘             └─┘
typ                          └───────────┘└───────────┘└─┘
doc                          └───────────┘             └─┘
txt                          └───────────┘             └─┘
par                          └───────────┘             └─┘
pid                                 └┘└─┘             └─┘
st   ─────────────────────────────────────────────────────┘└─
3292                          simp at h, revert h, apply and_implies _ (and_implies id or.inr),
id                                                                     └─────────┘ └┘ └────┘
src                          └───────┘  └──────┘  └────┘           └─┘ └─────────┘└┘└────┘
typ                          └───────┘  └──────┘  └────┘           └─┘ └─────────┘└┘└────┘
doc                          └───────┘  └──────┘  └────┘           └─┘                    
txt                          └───────┘  └──────┘  └────┘           └─┘                    
par                          └───────┘  └──────┘  └────┘           └─┘                    
pid                              └──┘        └┘                  └─┘                    
st   ────────────────────────────────┘└────────┘└───────────────────────────────────────────┘└─
3293                          intro h, transitivity j+1, apply nat.le_add_right, exact h } }
id                                                          └──────────────┘        
src                          └─────┘  └───────────┘   └────┘└──────────────┘  └────┘ 
typ                          └─────┘  └───────────┘  └────┘└──────────────┘  └────┘
doc                          └─────┘  └───────────┘    └────┘                  └────┘ 
txt                          └─────┘  └───────────┘    └────┘                  └────┘ 
par                          └─────┘  └───────────┘    └────┘                  └────┘ 
pid                               └┘                                               
st   ──────────────────────────────┘└────────────────┘└──────────────────────┘└────────┘└──┘
3294  
3295  /- product -/
3296  
3297  @[simp] theorem nil_product (l : list β) : product (@nil α) l = [] := rfl
id                                    └──┘     └─────┘   └─┘     └┘    └─┘
src                                   └──┘      └─────┘   └─┘       └┘    └─┘
typ                                   └──┘     └─────┘   └─┘     └┘    └─┘
doc    └──┘                                     └─────┘
3298  
3299  @[simp] theorem product_cons (a : α) (l₁ : list α) (l₂ : list β)
id                                             └──┘         └──┘ 
src                                             └──┘          └──┘
typ                                            └──┘         └──┘ 
doc    └──┘
3300          : product (a::l₁) l₂ = map (λ b, (a, b)) l₂ ++ product l₁ l₂ := rfl
id             └─────┘  └┘└┘  └┘  └─┘           └┘ └┘ └─────┘ └┘ └┘    └─┘
src            └─────┘   └┘        └─┘                 └┘ └─────┘          └─┘
typ            └─────┘  └┘└┘  └┘  └─┘           └┘ └┘ └─────┘ └┘ └┘    └─┘
doc            └─────┘                                      └─────┘
3301  
3302  @[simp] theorem product_nil : ∀ (l : list α), product l (@nil β) = []
id                                       └──┘    └─────┘    └─┘    └┘
src                                       └──┘     └─────┘     └─┘     └┘
typ                                      └──┘    └─────┘    └─┘    └┘
doc    └──┘                                        └─────┘
3303  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
3304  | (a::l) := by rw [product_cons, product_nil]; refl
id       └┘             └──────────┘  └─────────┘
src      └┘         └──┘└──────────┘└┘             └────
typ      └┘         └──┘└──────────┘└┘└─────────┘  └────
doc                 └──┘            └┘             └────
txt                 └──┘            └┘             └────
par                 └──┘            └┘             └────
pid                   └┘            └┘                 
st                 └───────────────┘└───────────┘└──────
3305  
src  
typ  
doc  
txt  
par  
pid  
st   
3306  @[simp] theorem mem_product {l₁ : list α} {l₂ : list β} {a : α} {b : β} :
id                                     └──┘         └──┘               
src                                    └──┘          └──┘
typ                                    └──┘         └──┘               
doc    └──┘
3307    (a, b) ∈ product l₁ l₂ ↔ a ∈ l₁ ∧ b ∈ l₂ :=
id          └─────┘ └┘ └┘    └┘    └┘
src           └─────┘                 
typ         └─────┘ └┘ └┘    └┘    └┘
doc             └─────┘
3308  by simp only [product, mem_bind, mem_map, prod.ext_iff, exists_prop,
id                 └─────┘  └──────┘  └─────┘  └──────────┘  └─────────┘
src     └─────────┘└─────┘└┘└──────┘└┘└─────┘└┘└──────────┘└┘└─────────┘└─
typ     └─────────┘└─────┘└┘└──────┘└┘└─────┘└┘└──────────┘└┘└─────────┘└─
doc     └─────────┘└─────┘└┘        └┘       └┘            └┘           └─
txt     └─────────┘       └┘        └┘       └┘            └┘           └─
par     └─────────┘       └┘        └┘       └┘            └┘           └─
pid         └──┘└┘       └┘        └┘       └┘            └┘           └─
st     └──────────────────────────────────────────────────────────────────
3309    and.left_comm, exists_and_distrib_left, exists_eq_left, exists_eq_right]
id     └───────────┘  └─────────────────────┘  └────────────┘  └─────────────┘
src  ─┘└───────────┘└┘└─────────────────────┘└┘└────────────┘└┘└─────────────┘└─
typ  ─┘└───────────┘└┘└─────────────────────┘└┘└────────────┘└┘└─────────────┘└─
doc  ─┘             └┘                       └┘              └┘               └─
txt  ─┘             └┘                       └┘              └┘               └─
par  ─┘             └┘                       └┘              └┘               └─
pid  ─┘             └┘                       └┘              └┘               
st   ───────────────────────────────────────────────────────────────────────────
3310  
src  
typ  
doc  
txt  
par  
pid  
st   
3311  theorem length_product (l₁ : list α) (l₂ : list β) :
id                                └──┘         └──┘ 
src                               └──┘          └──┘
typ                               └──┘         └──┘ 
3312    length (product l₁ l₂) = length l₁ * length l₂ :=
id     └────┘  └─────┘ └┘ └┘   └────┘ └┘  └────┘ └┘
src    └────┘  └─────┘         └────┘     └────┘
typ    └────┘  └─────┘ └┘ └┘   └────┘ └┘  └────┘ └┘
doc            └─────┘
3313  by induction l₁ with x l₁ IH; [exact (zero_mul _).symm,
id                └┘                      └──────┘
src     └────────┘  └───────────┘  └────┘ └──────┘└──────┘
typ     └────────┘└┘└───────────┘  └────┘ └──────┘└──────┘
doc     └────────┘  └───────────┘   └────┘         └──────┘
txt     └────────┘  └───────────┘   └────┘         └──────┘
par     └────────┘  └───────────┘   └────┘         └──────┘
pid                └──────────┘                 └─────┘
st     └─────────────────────────────────────────────────────
3314    simp only [length, product_cons, length_append, IH,
id                └────┘  └──────────┘  └───────────┘  └┘
src    └─────────┘└────┘└┘└──────────┘└┘└───────────┘└┘  └─
typ    └─────────┘└────┘└┘└──────────┘└┘└───────────┘└┘└┘└─
doc    └─────────┘      └┘            └┘             └┘  └─
txt    └─────────┘      └┘            └┘             └┘  └─
par    └─────────┘      └┘            └┘             └┘  └─
pid        └──┘└┘      └┘            └┘             └┘  └─
st   ──────────────────────────────────────────────────────
3315      right_distrib, one_mul, length_map, add_comm]]
id       └───────────┘  └─────┘  └────────┘  └──────┘
src  ───┘└───────────┘└┘└─────┘└┘└────────┘└┘└──────┘
typ  ───┘└───────────┘└┘└─────┘└┘└────────┘└┘└──────┘
doc  ───┘             └┘       └┘          └┘        
txt  ───┘             └┘       └┘          └┘        
par  ───┘             └┘       └┘          └┘        
pid  ───┘             └┘       └┘          └┘        
st   ─────────────────────────────────────────────────┘
3316  
3317  
3318  /- sigma -/
3319  section
3320  variable {σ : α → Type*}
3321  
3322  @[simp] theorem nil_sigma (l : Π a, list (σ a)) : (@nil α).sigma l = [] := rfl
id                                      └──┘          └─┘  └───┘    └┘    └─┘
src                                      └──┘            └─┘   └───┘     └┘    └─┘
typ                                     └──┘          └─┘  └───┘    └┘    └─┘
doc    └──┘                                                    └───┘
3323  
3324  @[simp] theorem sigma_cons (a : α) (l₁ : list α) (l₂ : Π a, list (σ a))
id                                           └──┘             └──┘   
src                                           └──┘               └──┘
typ                                          └──┘             └──┘   
doc    └──┘
3325          : (a::l₁).sigma l₂ = map (sigma.mk a) (l₂ a) ++ l₁.sigma l₂ := rfl
id              └┘└┘ └───┘  └┘  └─┘  └──────┘    └┘   └┘ └┘└────┘ └┘    └─┘
src              └┘   └───┘      └─┘  └──────┘           └┘   └────┘       └─┘
typ             └┘└┘ └───┘  └┘  └─┘  └──────┘    └┘   └┘ └┘└────┘ └┘    └─┘
doc                   └───┘                                    └────┘
3326  
3327  @[simp] theorem sigma_nil : ∀ (l : list α), l.sigma (λ a, @nil (σ a)) = []
id                                     └──┘    └────┘       └─┘       └┘
src                                     └──┘      └────┘        └─┘         └┘
typ                                    └──┘    └────┘       └─┘       └┘
doc    └──┘                                       └────┘
3328  | []     := rfl
id     └┘        └─┘
src    └┘        └─┘
typ    └┘        └─┘
3329  | (a::l) := by rw [sigma_cons, sigma_nil]; refl
id       └┘             └────────┘  └───────┘
src      └┘         └──┘└────────┘└┘           └────
typ      └┘         └──┘└────────┘└┘└───────┘  └────
doc                 └──┘          └┘           └────
txt                 └──┘          └┘           └────
par                 └──┘          └┘           └────
pid                   └┘          └┘               
st                 └─────────────┘└─────────┘└──────
3330  
src  
typ  
doc  
txt  
par  
pid  
st   
3331  @[simp] theorem mem_sigma {l₁ : list α} {l₂ : Π a, list (σ a)} {a : α} {b : σ a} :
id                                   └──┘             └──┘                   
src                                  └──┘               └──┘
typ                                  └──┘             └──┘                   
doc    └──┘
3332    sigma.mk a b ∈ l₁.sigma l₂ ↔ a ∈ l₁ ∧ b ∈ l₂ a :=
id     └──────┘    └┘└────┘ └┘    └┘    └┘ 
src    └──────┘        └────┘              
typ    └──────┘    └┘└────┘ └┘    └┘    └┘ 
doc                     └────┘
3333  by simp only [list.sigma, mem_bind, mem_map, exists_prop, exists_and_distrib_left,
id                 └────────┘  └──────┘  └─────┘  └─────────┘  └─────────────────────┘
src     └─────────┘└────────┘└┘└──────┘└┘└─────┘└┘└─────────┘└┘└─────────────────────┘└─
typ     └─────────┘└────────┘└┘└──────┘└┘└─────┘└┘└─────────┘└┘└─────────────────────┘└─
doc     └─────────┘└────────┘└┘        └┘       └┘           └┘                       └─
txt     └─────────┘          └┘        └┘       └┘           └┘                       └─
par     └─────────┘          └┘        └┘       └┘           └┘                       └─
pid         └──┘└┘          └┘        └┘       └┘           └┘                       └─
st     └────────────────────────────────────────────────────────────────────────────────
3334    and.left_comm, exists_eq_left, heq_iff_eq, exists_eq_right]
id     └───────────┘  └────────────┘  └────────┘  └─────────────┘
src  ─┘└───────────┘└┘└────────────┘└┘└────────┘└┘└─────────────┘└─
typ  ─┘└───────────┘└┘└────────────┘└┘└────────┘└┘└─────────────┘└─
doc  ─┘             └┘              └┘          └┘               └─
txt  ─┘             └┘              └┘          └┘               └─
par  ─┘             └┘              └┘          └┘               └─
pid  ─┘             └┘              └┘          └┘               
st   ──────────────────────────────────────────────────────────────
3335  
src  
typ  
doc  
txt  
par  
pid  
st   
3336  theorem length_sigma (l₁ : list α) (l₂ : Π a, list (σ a)) :
id                              └──┘             └──┘   
src                             └──┘               └──┘
typ                             └──┘             └──┘   
3337    length (l₁.sigma l₂) = (l₁.map (λ a, length (l₂ a))).sum :=
id     └────┘  └┘└────┘ └┘    └┘└──┘      └────┘  └┘    └─┘
src    └────┘    └────┘         └──┘       └────┘         └─┘
typ    └────┘  └┘└────┘ └┘    └┘└──┘      └────┘  └┘    └─┘
doc              └────┘                                    └─┘
3338  by induction l₁ with x l₁ IH; [refl,
id                └┘               
src     └────────┘  └───────────┘  └──┘
typ     └────────┘└┘└───────────┘  └──┘
doc     └────────┘  └───────────┘   └──┘
txt     └────────┘  └───────────┘   └──┘
par     └────────┘  └───────────┘   └──┘
pid                └──────────┘
st     └──────────────────────────────────
3339  simp only [map, sigma_cons, length_append, length_map, IH, sum_cons]]
id              └─┘  └────────┘  └───────────┘  └────────┘  └┘  └──────┘
src  └─────────┘└─┘└┘└────────┘└┘└───────────┘└┘└────────┘└┘  └┘└──────┘
typ  └─────────┘└─┘└┘└────────┘└┘└───────────┘└┘└────────┘└┘└┘└┘└──────┘
doc  └─────────┘   └┘          └┘             └┘          └┘  └┘        
txt  └─────────┘   └┘          └┘             └┘          └┘  └┘        
par  └─────────┘   └┘          └┘             └┘          └┘  └┘        
pid      └──┘└┘   └┘          └┘             └┘          └┘  └┘        
st   ────────────────────────────────────────────────────────────────────┘
3340  end
3341  
3342  /- of_fn -/
3343  
3344  theorem length_of_fn_aux {n} (f : fin n → α) :
id                                     └─┘    
src                                    └─┘
typ                                    └─┘    
3345    ∀ m h l, length (of_fn_aux f m h l) = length l + m
id           └────┘  └───────┘       └────┘   
src             └────┘  └───────┘           └────┘   
typ          └────┘  └───────┘       └────┘   
3346  | 0        h l := rfl
id                     └─┘
src                    └─┘
typ                    └─┘
3347  | (succ m) h l := (length_of_fn_aux m _ _).trans (succ_add _ _)
id      └──┘           └──────────────┘       └───┘   └──────┘
src     └──┘                                   └───┘   └──────┘
typ     └──┘           └──────────────┘       └───┘   └──────┘
3348  
3349  @[simp] theorem length_of_fn {n} (f : fin n → α) : length (of_fn f) = n :=
id                                         └─┘        └────┘  └───┘    
src                                        └─┘          └────┘  └───┘    
typ                                        └─┘        └────┘  └───┘    
doc    └──┘
3350  (length_of_fn_aux f _ _ _).trans (zero_add _)
id    └──────────────┘        └───┘   └──────┘
src   └──────────────┘         └───┘   └──────┘
typ   └──────────────┘        └───┘   └──────┘
3351  
3352  theorem nth_of_fn_aux {n} (f : fin n → α) (i) :
id                                  └─┘    
src                                 └─┘
typ                                 └─┘    
3353    ∀ m h l,
id         
typ        
3354      (∀ i, nth l i = of_fn_nth_val f (i + m)) →
id            └─┘    └───────────┘     
src            └─┘      └───────────┘      
typ           └─┘    └───────────┘     
3355       nth (of_fn_aux f m h l) i = of_fn_nth_val f i
id        └─┘  └───────┘        └───────────┘  
src       └─┘  └───────┘             └───────────┘
typ       └─┘  └───────┘        └───────────┘  
3356  | 0        h l H := H i
id                        
typ                       
3357  | (succ m) h l H := nth_of_fn_aux m _ _ begin
id      └──┘            └───────────┘
src     └──┘
typ     └──┘            └───────────┘
st                                           └─────
3358    intro j, cases j with j,
id                    
src    └─────┘  └────┘ └─────┘
typ    └─────┘  └────┘└─────┘
doc    └─────┘  └────┘ └─────┘
txt    └─────┘  └────┘ └─────┘
par    └─────┘  └────┘ └─────┘
pid         └┘        └─────┘
st   ────────┘└──────────────┘└─
3359    { simp only [nth, of_fn_nth_val, zero_add, dif_pos (show m < n, from h)] },
id                  └─┘  └───────────┘  └──────┘  └─────┘                
src      └─────────┘└─┘└┘└───────────┘└┘└──────┘└┘└─────┘       └─────┘ └─┘
typ      └─────────┘└─┘└┘└───────────┘└┘└──────┘└┘└─────┘     └─────┘└─┘
doc      └─────────┘   └┘             └┘        └┘               └─────┘ └─┘
txt      └─────────┘   └┘             └┘        └┘               └─────┘ └─┘
par      └─────────┘   └┘             └┘        └┘               └─────┘ └─┘
pid          └──┘└┘   └┘             └┘        └┘               └─────┘ └┘
st   ───┘└─────────────────────────────────────────────────────────────────────┘└┘
3360    { simp only [nth, H, succ_add] }
id                  └─┘    └──────┘
src      └─────────┘└─┘└┘ └┘└──────┘└┘
typ      └─────────┘└─┘└┘└┘└──────┘└┘
doc      └─────────┘   └┘ └┘        └┘
txt      └─────────┘   └┘ └┘        └┘
par      └─────────┘   └┘ └┘        └┘
pid          └──┘└┘   └┘ └┘        
st   ────────────────────────────────┘└─
3361  end
st   ──┘
3362  
3363  @[simp] theorem nth_of_fn {n} (f : fin n → α) (i) :
id                                      └─┘    
src                                     └─┘
typ                                     └─┘    
doc    └──┘
3364    nth (of_fn f) i = of_fn_nth_val f i :=
id     └─┘  └───┘     └───────────┘  
src    └─┘  └───┘       └───────────┘
typ    └─┘  └───┘     └───────────┘  
3365  nth_of_fn_aux f _ _ _ _ $ λ i,
id   └───────────┘              
src  └───────────┘
typ  └───────────┘              
3366  by simp only [of_fn_nth_val, dif_neg (not_lt.2 (le_add_left n i))]; refl
id                 └───────────┘  └─────┘  └────┘    └─────────┘  
src     └─────────┘└───────────┘└┘└─────┘ └────┘└─┘ └─────────┘  └─┘  └────
typ     └─────────┘└───────────┘└┘└─────┘ └────┘└─┘ └─────────┘└─┘  └────
doc     └─────────┘             └┘              └─┘              └─┘  └────
txt     └─────────┘             └┘              └─┘              └─┘  └────
par     └─────────┘             └┘              └─┘              └─┘  └────
pid         └──┘└┘             └┘              └─┘              └─┘      
st     └──────────────────────────────────────────────────────────────────────
3367  
src  
typ  
doc  
txt  
par  
pid  
st   
3368  @[simp] theorem nth_le_of_fn {n} (f : fin n → α) (i : fin n) :
id                                         └─┘           └─┘ 
src                                        └─┘             └─┘
typ                                        └─┘           └─┘ 
doc    └──┘
3369    nth_le (of_fn f) i.1 ((length_of_fn f).symm ▸ i.2) = f i :=
id     └────┘  └───┘       └──────────┘  └──┘        
src    └────┘  └───┘         └──────────┘   └──┘       
typ    └────┘  └───┘       └──────────┘  └──┘        
3370  option.some.inj $ by rw [← nth_le_nth];
id   └─────────────┘            └────────┘
src  └─────────────┘      └────┘└────────┘
typ  └─────────────┘      └────┘└────────┘
doc                       └────┘          
txt                       └────┘          
par                       └────┘          
pid                         └──┘          
st                       └───────────────┘└─
3371    simp only [list.nth_of_fn, of_fn_nth_val, fin.eta, dif_pos i.2]
id                └────────────┘  └───────────┘  └─────┘  └─────┘ 
src    └─────────┘└────────────┘└┘└───────────┘└┘└─────┘└┘└─────┘ └───
typ    └─────────┘└────────────┘└┘└───────────┘└┘└─────┘└┘└─────┘└───
doc    └─────────┘              └┘             └┘       └┘        └───
txt    └─────────┘              └┘             └┘       └┘        └───
par    └─────────┘              └┘             └┘       └┘        └───
pid        └──┘└┘              └┘             └┘       └┘        └─┘
st   ──────────────────────────────────────────────────────────────────
3372  
src  
typ  
doc  
txt  
par  
pid  
st   
3373  theorem array_eq_of_fn {n} (a : array n α) : a.to_list = of_fn a.read :=
id                                   └───┘      └──────┘  └───┘ └───┘
src                                  └───┘         └──────┘  └───┘  └───┘
typ                                  └───┘      └──────┘  └───┘ └───┘
3374  suffices ∀ {m h l}, d_array.rev_iterate_aux a
id                    └─────────────────────┘ 
src                      └─────────────────────┘
typ                   └─────────────────────┘ 
3375    (λ i, cons) m h l = of_fn_aux (d_array.read a) m h l, from this,
id          └──┘      └───────┘  └──────────┘            └──┘
src          └──┘         └───────┘  └──────────┘
typ         └──┘      └───────┘  └──────────┘            └──┘
3376  begin
st   └─────
3377    intros, induction m with m IH generalizing l, {refl},
id                       
src    └────┘  └────────┘ └───────────────────────┘   └──┘
typ    └────┘  └────────┘└───────────────────────┘   └──┘
doc    └────┘  └────────┘ └───────────────────────┘   └──┘
txt    └────┘  └────────┘ └───────────────────────┘   └──┘
par    └────┘  └────────┘ └───────────────────────┘   └──┘
pid                      └───────┘└─────────────┘
st   ───────┘└────────────────────────────────────┘└─────┘└┘
3378    simp only [d_array.rev_iterate_aux, of_fn_aux, IH]
id                └─────────────────────┘  └───────┘
src    └─────────┘└─────────────────────┘└┘└───────┘└┘  └┘
typ    └─────────┘└─────────────────────┘└┘└───────┘└┘└┘└┘
doc    └─────────┘                       └┘         └┘  └┘
txt    └─────────┘                       └┘         └┘  └┘
par    └─────────┘                       └┘         └┘  └┘
pid        └──┘└┘                       └┘         └┘  
st   ────────────────────────────────────────────────────┘
3379  end
st   └─┘
3380  
3381  theorem of_fn_zero (f : fin 0 → α) : of_fn f = [] := rfl
id                           └─┘         └───┘   └┘    └─┘
src                          └─┘          └───┘    └┘    └─┘
typ                          └─┘         └───┘   └┘    └─┘
3382  
3383  theorem of_fn_succ {n} (f : fin (succ n) → α) :
id                               └─┘  └──┘     
src                              └─┘  └──┘
typ                              └─┘  └──┘     
3384    of_fn f = f 0 :: of_fn (λ i, f i.succ) :=
id     └───┘      └┘ └───┘       └───┘
src    └───┘        └┘ └───┘          └───┘
typ    └───┘      └┘ └───┘       └───┘
3385  suffices ∀ {m h l}, of_fn_aux f (succ m) (succ_le_succ h) l =
id                    └───────┘   └──┘    └──────────┘    
src                      └───────┘    └──┘     └──────────┘      
typ                   └───────┘   └──┘    └──────────┘    
3386    f 0 :: of_fn_aux (λ i, f i.succ) m h l, from this,
id        └┘ └───────┘       └───┘           └──┘
src        └┘ └───────┘          └───┘
typ       └┘ └───────┘       └───┘           └──┘
3387  begin
st   └─────
3388    intros, induction m with m IH generalizing l, {refl},
id                       
src    └────┘  └────────┘ └───────────────────────┘   └──┘
typ    └────┘  └────────┘└───────────────────────┘   └──┘
doc    └────┘  └────────┘ └───────────────────────┘   └──┘
txt    └────┘  └────────┘ └───────────────────────┘   └──┘
par    └────┘  └────────┘ └───────────────────────┘   └──┘
pid                      └───────┘└─────────────┘
st   ───────┘└────────────────────────────────────┘└─────┘└┘
3389    rw [of_fn_aux, IH], refl
id         └───────┘
src    └──┘└───────┘└┘    └───┘
typ    └──┘└───────┘└┘└┘  └───┘
doc    └──┘         └┘    └───┘
txt    └──┘         └┘    └───┘
par    └──┘         └┘    └───┘
pid      └┘         └┘        
st   ──────────────┘└──┘└─────┘
3390  end
st   └─┘
3391  
3392  theorem of_fn_nth_le : ∀ l : list α, of_fn (λ i, nth_le l i.1 i.2) = l
id                               └──┘   └───┘      └────┘        
src                               └──┘    └───┘       └────┘          
typ                              └──┘   └───┘      └────┘        
3393  | [] := rfl
id     └┘    └─┘
src    └┘    └─┘
typ    └┘    └─┘
3394  | (a::l) := by rw of_fn_succ; congr; simp only [fin.succ_val]; exact of_fn_nth_le l
id       └┘            └────────┘                    └──────────┘         └──────────┘ 
src      └┘         └─┘└────────┘  └───┘  └─────────┘└──────────┘  └────┘             
typ      └┘         └─┘└────────┘  └───┘  └─────────┘└──────────┘  └────┘└──────────┘
doc                 └─┘                   └─────────┘              └────┘             
txt                 └─┘            └───┘  └─────────┘              └────┘             
par                 └─┘            └───┘  └─────────┘              └────┘             
pid                                          └──┘└┘                                
st                 └─────────────────────────────────────────────────────────────────────
3395  
src  
typ  
doc  
txt  
par  
pid  
st   
3396  /- disjoint -/
src  ──────────────┘
typ  ──────────────┘
doc  ──────────────┘
txt  ──────────────┘
par  ──────────────┘
pid  ──────────────┘
st   ──────────────┘
3397  section disjoint
3398  
3399  theorem disjoint.symm {l₁ l₂ : list α} (d : disjoint l₁ l₂) : disjoint l₂ l₁
id                                  └──┘        └──────┘ └┘ └┘    └──────┘ └┘ └┘
src                                 └──┘         └──────┘          └──────┘
typ                                 └──┘        └──────┘ └┘ └┘    └──────┘ └┘ └┘
doc                                              └──────┘          └──────┘
3400  | a i₂ i₁ := d i₁ i₂
id       └┘ └┘    
typ      └┘ └┘    
3401  
3402  @[simp] theorem disjoint_comm {l₁ l₂ : list α} : disjoint l₁ l₂ ↔ disjoint l₂ l₁ :=
id                                          └──┘     └──────┘ └┘ └┘  └──────┘ └┘ └┘
src                                         └──┘      └──────┘        └──────┘
typ                                         └──┘     └──────┘ └┘ └┘  └──────┘ └┘ └┘
doc    └──┘                                           └──────┘         └──────┘
3403  ⟨disjoint.symm, disjoint.symm⟩
id    └───────────┘  └───────────┘
src   └───────────┘  └───────────┘
typ   └───────────┘  └───────────┘
3404  
3405  theorem disjoint_left {l₁ l₂ : list α} : disjoint l₁ l₂ ↔ ∀ {a}, a ∈ l₁ → a ∉ l₂ := iff.rfl
id                                  └──┘     └──────┘ └┘ └┘          └┘     └┘    └─────┘
src                                 └──┘      └──────┘                                └─────┘
typ                                 └──┘     └──────┘ └┘ └┘          └┘     └┘    └─────┘
doc                                           └──────┘
3406  
3407  theorem disjoint_right {l₁ l₂ : list α} : disjoint l₁ l₂ ↔ ∀ {a}, a ∈ l₂ → a ∉ l₁ :=
id                                   └──┘     └──────┘ └┘ └┘          └┘     └┘
src                                  └──┘      └──────┘                         
typ                                  └──┘     └──────┘ └┘ └┘          └┘     └┘
doc                                            └──────┘
3408  disjoint_comm
id   └───────────┘
src  └───────────┘
typ  └───────────┘
3409  
3410  theorem disjoint_iff_ne {l₁ l₂ : list α} : disjoint l₁ l₂ ↔ ∀ a ∈ l₁, ∀ b ∈ l₂, a ≠ b :=
id                                    └──┘     └──────┘ └┘ └┘       └┘       └┘    
src                                   └──┘      └──────┘                              
typ                                   └──┘     └──────┘ └┘ └┘       └┘       └┘    
doc                                             └──────┘
3411  by simp only [disjoint_left, imp_not_comm, forall_eq']
id                 └───────────┘  └──────────┘  └────────┘
src     └─────────┘└───────────┘└┘└──────────┘└┘└────────┘└─
typ     └─────────┘└───────────┘└┘└──────────┘└┘└────────┘└─
doc     └─────────┘             └┘            └┘          └─
txt     └─────────┘             └┘            └┘          └─
par     └─────────┘             └┘            └┘          └─
pid         └──┘└┘             └┘            └┘          
st     └────────────────────────────────────────────────────
3412  
src  
typ  
doc  
txt  
par  
pid  
st   
3413  theorem disjoint_of_subset_left {l₁ l₂ l : list α} (ss : l₁ ⊆ l) (d : disjoint l l₂) : disjoint l₁ l₂
id                                              └──┘         └┘         └──────┘  └┘    └──────┘ └┘ └┘
src                                             └──┘                      └──────┘         └──────┘
typ                                             └──┘         └┘         └──────┘  └┘    └──────┘ └┘ └┘
doc                                                                        └──────┘         └──────┘
3414  | x m₁ := d (ss m₁)
id       └┘      └┘
typ      └┘      └┘
3415  
3416  theorem disjoint_of_subset_right {l₁ l₂ l : list α} (ss : l₂ ⊆ l) (d : disjoint l₁ l) : disjoint l₁ l₂
id                                               └──┘         └┘         └──────┘ └┘     └──────┘ └┘ └┘
src                                              └──┘                      └──────┘         └──────┘
typ                                              └──┘         └┘         └──────┘ └┘     └──────┘ └┘ └┘
doc                                                                         └──────┘         └──────┘
3417  | x m m₁ := d m (ss m₁)
id        └┘        └┘
typ       └┘        └┘
3418  
3419  theorem disjoint_of_disjoint_cons_left {a : α} {l₁ l₂} : disjoint (a::l₁) l₂ → disjoint l₁ l₂ :=
id                                                           └──────┘  └┘└┘  └┘   └──────┘ └┘ └┘
src                                                           └──────┘   └┘         └──────┘
typ                                                          └──────┘  └┘└┘  └┘   └──────┘ └┘ └┘
doc                                                           └──────┘              └──────┘
3420  disjoint_of_subset_left (list.subset_cons _ _)
id   └─────────────────────┘  └──────────────┘
src  └─────────────────────┘  └──────────────┘
typ  └─────────────────────┘  └──────────────┘
3421  
3422  theorem disjoint_of_disjoint_cons_right {a : α} {l₁ l₂} : disjoint l₁ (a::l₂) → disjoint l₁ l₂ :=
id                                                            └──────┘ └┘  └┘└┘    └──────┘ └┘ └┘
src                                                            └──────┘      └┘      └──────┘
typ                                                           └──────┘ └┘  └┘└┘    └──────┘ └┘ └┘
doc                                                            └──────┘              └──────┘
3423  disjoint_of_subset_right (list.subset_cons _ _)
id   └──────────────────────┘  └──────────────┘
src  └──────────────────────┘  └──────────────┘
typ  └──────────────────────┘  └──────────────┘
3424  
3425  @[simp] theorem disjoint_nil_left (l : list α) : disjoint [] l
id                                          └──┘     └──────┘ └┘ 
src                                         └──┘      └──────┘ └┘
typ                                         └──┘     └──────┘ └┘ 
doc    └──┘                                           └──────┘
3426  | a := (not_mem_nil a).elim
id          └─────────┘   └──┘
src          └─────────┘   └──┘
typ         └─────────┘   └──┘
3427  
3428  @[simp] theorem singleton_disjoint {l : list α} {a : α} : disjoint [a] l ↔ a ∉ l :=
id                                           └──┘            └──────┘      
src                                          └──┘              └──────┘        
typ                                          └──┘            └──────┘      
doc    └──┘                                                    └──────┘
3429  by simp only [disjoint, mem_singleton, forall_eq]; refl
id                 └──────┘  └───────────┘  └───────┘
src     └─────────┘└──────┘└┘└───────────┘└┘└───────┘  └────
typ     └─────────┘└──────┘└┘└───────────┘└┘└───────┘  └────
doc     └─────────┘└──────┘└┘             └┘           └────
txt     └─────────┘        └┘             └┘           └────
par     └─────────┘        └┘             └┘           └────
pid         └──┘└┘        └┘             └┘               
st     └─────────────────────────────────────────────────────
3430  
src  
typ  
doc  
txt  
par  
pid  
st   
3431  @[simp] theorem disjoint_singleton {l : list α} {a : α} : disjoint l [a] ↔ a ∉ l :=
id                                           └──┘            └──────┘      
src                                          └──┘              └──────┘        
typ                                          └──┘            └──────┘      
doc    └──┘                                                    └──────┘
3432  by rw disjoint_comm; simp only [singleton_disjoint]
id         └───────────┘             └────────────────┘
src     └─┘└───────────┘  └─────────┘└────────────────┘└─
typ     └─┘└───────────┘  └─────────┘└────────────────┘└─
doc     └─┘               └─────────┘                  └─
txt     └─┘               └─────────┘                  └─
par     └─┘               └─────────┘                  └─
pid                          └──┘└┘                  
st     └─────────────────────────────────────────────────
3433  
src  
typ  
doc  
txt  
par  
pid  
st   
3434  @[simp] theorem disjoint_append_left {l₁ l₂ l : list α} :
id                                                   └──┘ 
src                                                  └──┘
typ                                                  └──┘ 
doc    └──┘
3435    disjoint (l₁++l₂) l ↔ disjoint l₁ l ∧ disjoint l₂ l :=
id     └──────┘  └┘└┘└┘    └──────┘ └┘   └──────┘ └┘ 
src    └──────┘    └┘       └──────┘       └──────┘
typ    └──────┘  └┘└┘└┘    └──────┘ └┘   └──────┘ └┘ 
doc    └──────┘              └──────┘        └──────┘
3436  by simp only [disjoint, mem_append, or_imp_distrib, forall_and_distrib]
id                 └──────┘  └────────┘  └────────────┘  └────────────────┘
src     └─────────┘└──────┘└┘└────────┘└┘└────────────┘└┘└────────────────┘└─
typ     └─────────┘└──────┘└┘└────────┘└┘└────────────┘└┘└────────────────┘└─
doc     └─────────┘└──────┘└┘          └┘              └┘                  └─
txt     └─────────┘        └┘          └┘              └┘                  └─
par     └─────────┘        └┘          └┘              └┘                  └─
pid         └──┘└┘        └┘          └┘              └┘                  
st     └─────────────────────────────────────────────────────────────────────
3437  
src  
typ  
doc  
txt  
par  
pid  
st   
3438  @[simp] theorem disjoint_append_right {l₁ l₂ l : list α} :
id                                                    └──┘ 
src                                                   └──┘
typ                                                   └──┘ 
doc    └──┘
3439    disjoint l (l₁++l₂) ↔ disjoint l l₁ ∧ disjoint l l₂ :=
id     └──────┘   └┘└┘└┘   └──────┘  └┘  └──────┘  └┘
src    └──────┘      └┘     └──────┘       └──────┘
typ    └──────┘   └┘└┘└┘   └──────┘  └┘  └──────┘  └┘
doc    └──────┘              └──────┘        └──────┘
3440  disjoint_comm.trans $ by simp only [disjoint_comm, disjoint_append_left]
id   └───────────┘└────┘                 └───────────┘  └──────────────────┘
src  └───────────┘└────┘      └─────────┘└───────────┘└┘└──────────────────┘└─
typ  └───────────┘└────┘      └─────────┘└───────────┘└┘└──────────────────┘└─
doc                           └─────────┘             └┘                    └─
txt                           └─────────┘             └┘                    └─
par                           └─────────┘             └┘                    └─
pid                               └──┘└┘             └┘                    
st                           └────────────────────────────────────────────────
3441  
src  
typ  
doc  
txt  
par  
pid  
st   
3442  @[simp] theorem disjoint_cons_left {a : α} {l₁ l₂ : list α} :
id                                                      └──┘ 
src                                                      └──┘
typ                                                     └──┘ 
doc    └──┘
3443    disjoint (a::l₁) l₂ ↔ a ∉ l₂ ∧ disjoint l₁ l₂ :=
id     └──────┘  └┘└┘  └┘    └┘  └──────┘ └┘ └┘
src    └──────┘   └┘               └──────┘
typ    └──────┘  └┘└┘  └┘    └┘  └──────┘ └┘ └┘
doc    └──────┘                       └──────┘
3444  (@disjoint_append_left _ [a] l₁ l₂).trans $ by simp only [singleton_disjoint]
id     └──────────────────┘    └┘ └┘ └───┘                  └────────────────┘
src    └──────────────────┘           └───┘       └─────────┘└────────────────┘└─
typ    └──────────────────┘    └┘ └┘ └───┘       └─────────┘└────────────────┘└─
doc                                                 └─────────┘                  └─
txt                                                 └─────────┘                  └─
par                                                 └─────────┘                  └─
pid                                                     └──┘└┘                  
st                                                 └───────────────────────────────
3445  
src  
typ  
doc  
txt  
par  
pid  
st   
3446  @[simp] theorem disjoint_cons_right {a : α} {l₁ l₂ : list α} :
id                                                       └──┘ 
src                                                       └──┘
typ                                                      └──┘ 
doc    └──┘
3447    disjoint l₁ (a::l₂) ↔ a ∉ l₁ ∧ disjoint l₁ l₂ :=
id     └──────┘ └┘  └┘└┘     └┘  └──────┘ └┘ └┘
src    └──────┘      └┘            └──────┘
typ    └──────┘ └┘  └┘└┘     └┘  └──────┘ └┘ └┘
doc    └──────┘                       └──────┘
3448  disjoint_comm.trans $ by simp only [disjoint_comm, disjoint_cons_left]
id   └───────────┘└────┘                 └───────────┘  └────────────────┘
src  └───────────┘└────┘      └─────────┘└───────────┘└┘└────────────────┘└─
typ  └───────────┘└────┘      └─────────┘└───────────┘└┘└────────────────┘└─
doc                           └─────────┘             └┘                  └─
txt                           └─────────┘             └┘                  └─
par                           └─────────┘             └┘                  └─
pid                               └──┘└┘             └┘                  
st                           └──────────────────────────────────────────────
3449  
src  
typ  
doc  
txt  
par  
pid  
st   
3450  theorem disjoint_of_disjoint_append_left_left {l₁ l₂ l : list α} (d : disjoint (l₁++l₂) l) : disjoint l₁ l :=
id                                                            └──┘        └──────┘  └┘└┘└┘      └──────┘ └┘ 
src                                                           └──┘         └──────┘    └┘         └──────┘
typ                                                           └──┘        └──────┘  └┘└┘└┘      └──────┘ └┘ 
doc                                                                        └──────┘               └──────┘
3451  (disjoint_append_left.1 d).1
id    └──────────────────┘   
src   └──────────────────┘    
typ   └──────────────────┘   
3452  
3453  theorem disjoint_of_disjoint_append_left_right {l₁ l₂ l : list α} (d : disjoint (l₁++l₂) l) : disjoint l₂ l :=
id                                                             └──┘        └──────┘  └┘└┘└┘      └──────┘ └┘ 
src                                                            └──┘         └──────┘    └┘         └──────┘
typ                                                            └──┘        └──────┘  └┘└┘└┘      └──────┘ └┘ 
doc                                                                         └──────┘               └──────┘
3454  (disjoint_append_left.1 d).2
id    └──────────────────┘   
src   └──────────────────┘    
typ   └──────────────────┘   
3455  
3456  theorem disjoint_of_disjoint_append_right_left {l₁ l₂ l : list α} (d : disjoint l (l₁++l₂)) : disjoint l l₁ :=
id                                                             └──┘        └──────┘   └┘└┘└┘     └──────┘  └┘
src                                                            └──┘         └──────┘      └┘       └──────┘
typ                                                            └──┘        └──────┘   └┘└┘└┘     └──────┘  └┘
doc                                                                         └──────┘               └──────┘
3457  (disjoint_append_right.1 d).1
id    └───────────────────┘   
src   └───────────────────┘    
typ   └───────────────────┘   
3458  
3459  theorem disjoint_of_disjoint_append_right_right {l₁ l₂ l : list α} (d : disjoint l (l₁++l₂)) : disjoint l l₂ :=
id                                                              └──┘        └──────┘   └┘└┘└┘     └──────┘  └┘
src                                                             └──┘         └──────┘      └┘       └──────┘
typ                                                             └──┘        └──────┘   └┘└┘└┘     └──────┘  └┘
doc                                                                          └──────┘               └──────┘
3460  (disjoint_append_right.1 d).2
id    └───────────────────┘   
src   └───────────────────┘    
typ   └───────────────────┘   
3461  
3462  end disjoint
3463  
3464  /- union -/
3465  section union
3466  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
3467  
3468  @[simp] theorem nil_union (l : list α) : [] ∪ l = l := rfl
id                                  └──┘     └┘        └─┘
src                                 └──┘      └┘          └─┘
typ                                 └──┘     └┘        └─┘
doc    └──┘
3469  
3470  @[simp] theorem cons_union (l₁ l₂ : list α) (a : α) : a :: l₁ ∪ l₂ = insert a (l₁ ∪ l₂) := rfl
id                                       └──┘             └┘ └┘  └┘  └────┘   └┘  └┘     └─┘
src                                      └──┘                └┘         └────┘               └─┘
typ                                      └──┘             └┘ └┘  └┘  └────┘   └┘  └┘     └─┘
doc    └──┘
3471  
3472  @[simp] theorem mem_union {l₁ l₂ : list α} {a : α} : a ∈ l₁ ∪ l₂ ↔ a ∈ l₁ ∨ a ∈ l₂ :=
id                                      └──┘              └┘  └┘    └┘    └┘
src                                     └──┘                                  
typ                                     └──┘              └┘  └┘    └┘    └┘
doc    └──┘
3473  by induction l₁; simp only [nil_union, not_mem_nil, false_or, cons_union, mem_insert_iff, mem_cons_iff, or_assoc, *]
id                └┘             └───────┘  └─────────┘  └──────┘  └────────┘  └────────────┘  └──────────┘  └──────┘
src     └────────┘    └─────────┘└───────┘└┘└─────────┘└┘└──────┘└┘└────────┘└┘└────────────┘└┘└──────────┘└┘└──────┘└────
typ     └────────┘└┘  └─────────┘└───────┘└┘└─────────┘└┘└──────┘└┘└────────┘└┘└────────────┘└┘└──────────┘└┘└──────┘└────
doc     └────────┘    └─────────┘         └┘           └┘        └┘          └┘              └┘            └┘        └────
txt     └────────┘    └─────────┘         └┘           └┘        └┘          └┘              └┘            └┘        └────
par     └────────┘    └─────────┘         └┘           └┘        └┘          └┘              └┘            └┘        └────
pid                      └──┘└┘         └┘           └┘        └┘          └┘              └┘            └┘        └──┘
st     └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
3474  
src  
typ  
doc  
txt  
par  
pid  
st   
3475  theorem mem_union_left {a : α} {l₁ : list α} (h : a ∈ l₁) (l₂ : list α) : a ∈ l₁ ∪ l₂ :=
id                                       └──┘          └┘        └──┘       └┘  └┘
src                                       └──┘                      └──┘            
typ                                      └──┘          └┘        └──┘       └┘  └┘
3476  mem_union.2 (or.inl h)
id   └───────┘   └────┘ 
src  └───────┘   └────┘
typ  └───────┘   └────┘ 
3477  
3478  theorem mem_union_right {a : α} (l₁ : list α) {l₂ : list α} (h : a ∈ l₂) : a ∈ l₁ ∪ l₂ :=
id                                        └──┘         └──┘          └┘      └┘  └┘
src                                        └──┘          └──┘                        
typ                                       └──┘         └──┘          └┘      └┘  └┘
3479  mem_union.2 (or.inr h)
id   └───────┘   └────┘ 
src  └───────┘   └────┘
typ  └───────┘   └────┘ 
3480  
3481  theorem sublist_suffix_of_union : ∀ l₁ l₂ : list α, ∃ t, t <+ l₁ ∧ t ++ l₂ = l₁ ∪ l₂
id                                       └┘      └──┘      └┘ └┘   └┘ └┘  └┘  └┘
src                                              └──┘         └┘       └┘        
typ                                      └┘      └──┘      └┘ └┘   └┘ └┘  └┘  └┘
3482  | [] l₂ := ⟨[], by refl, rfl⟩
id     └┘        └┘           └─┘
src    └┘        └┘     └──┘  └─┘
typ    └┘        └┘     └──┘  └─┘
doc                     └──┘
txt                     └──┘
par                     └──┘
st                     └───┘
3483  | (a::l₁) l₂ := let ⟨t, s, e⟩ := sublist_suffix_of_union l₁ l₂ in
id      └┘└┘  └┘    └─┘            └─────────────────────┘
src      └┘
typ     └┘└┘  └┘    └─┘            └─────────────────────┘
3484    if h : a ∈ l₁ ∪ l₂
id     └┘           
src    └┘           
typ    └┘           
3485    then ⟨t, sublist_cons_of_sublist _ s, by simp only [e, cons_union, insert_of_mem h]⟩
id              └─────────────────────┘                      └────────┘  └───────────┘ 
src             └─────────────────────┘         └─────────┘ └┘└────────┘└┘└───────────┘ 
typ             └─────────────────────┘         └─────────┘└┘└────────┘└┘└───────────┘
doc                                             └─────────┘ └┘          └┘              
txt                                             └─────────┘ └┘          └┘              
par                                             └─────────┘ └┘          └┘              
pid                                                 └──┘└┘ └┘          └┘              
st                                             └─────────────────────────────────────────┘
3486    else ⟨a::t, cons_sublist_cons _ s, by simp only [cons_append, cons_union, e, insert_of_not_mem h]; split; refl⟩
id           └┘   └───────────────┘                    └─────────┘  └────────┘    └───────────────┘ 
src           └┘   └───────────────┘         └─────────┘└─────────┘└┘└────────┘└┘ └┘└───────────────┘   └───┘  └──┘
typ          └┘   └───────────────┘         └─────────┘└─────────┘└┘└────────┘└┘└┘└───────────────┘  └───┘  └──┘
doc                                          └─────────┘           └┘          └┘ └┘                    └───┘  └──┘
txt                                          └─────────┘           └┘          └┘ └┘                    └───┘  └──┘
par                                          └─────────┘           └┘          └┘ └┘                    └───┘  └──┘
pid                                              └──┘└┘           └┘          └┘ └┘                  
st                                          └───────────────────────────────────────────────────────────────────────┘
3487  
3488  theorem suffix_union_right (l₁ l₂ : list α) : l₂ <:+ l₁ ∪ l₂ :=
id                                       └──┘     └┘ └─┘ └┘  └┘
src                                      └──┘         └─┘    
typ                                      └──┘     └┘ └─┘ └┘  └┘
doc                                                   └─┘
3489  (sublist_suffix_of_union l₁ l₂).imp (λ a, and.right)
id    └─────────────────────┘ └┘ └┘ └─┘       └───────┘
src   └─────────────────────┘       └─┘        └───────┘
typ   └─────────────────────┘ └┘ └┘ └─┘       └───────┘
3490  
3491  theorem union_sublist_append (l₁ l₂ : list α) : l₁ ∪ l₂ <+ l₁ ++ l₂ :=
id                                         └──┘     └┘  └┘ └┘ └┘ └┘ └┘
src                                        └──┘             └┘    └┘
typ                                        └──┘     └┘  └┘ └┘ └┘ └┘ └┘
3492  let ⟨t, s, e⟩ := sublist_suffix_of_union l₁ l₂ in
id   └─┘            └─────────────────────┘ └┘ └┘
src                   └─────────────────────┘
typ  └─┘            └─────────────────────┘ └┘ └┘
3493  e ▸ (append_sublist_append_right _).2 s
id       └─────────────────────────┘   
src      └─────────────────────────┘   
typ      └─────────────────────────┘   
3494  
3495  theorem forall_mem_union {p : α → Prop} {l₁ l₂ : list α} :
id                                                   └──┘ 
src                                                   └──┘
typ                                                  └──┘ 
3496    (∀ x ∈ l₁ ∪ l₂, p x) ↔ (∀ x ∈ l₁, p x) ∧ (∀ x ∈ l₂, p x) :=
id           └┘  └┘            └┘            └┘   
src                                         
typ          └┘  └┘            └┘            └┘   
3497  by simp only [mem_union, or_imp_distrib, forall_and_distrib]
id                 └───────┘  └────────────┘  └────────────────┘
src     └─────────┘└───────┘└┘└────────────┘└┘└────────────────┘└─
typ     └─────────┘└───────┘└┘└────────────┘└┘└────────────────┘└─
doc     └─────────┘         └┘              └┘                  └─
txt     └─────────┘         └┘              └┘                  └─
par     └─────────┘         └┘              └┘                  └─
pid         └──┘└┘         └┘              └┘                  
st     └──────────────────────────────────────────────────────────
3498  
src  
typ  
doc  
txt  
par  
pid  
st   
3499  theorem forall_mem_of_forall_mem_union_left {p : α → Prop} {l₁ l₂ : list α}
id                                                                      └──┘ 
src                                                                      └──┘
typ                                                                     └──┘ 
3500     (h : ∀ x ∈ l₁ ∪ l₂, p x) : ∀ x ∈ l₁, p x :=
id                └┘  └┘            └┘   
src                   
typ               └┘  └┘            └┘   
3501  (forall_mem_union.1 h).1
id    └──────────────┘   
src   └──────────────┘    
typ   └──────────────┘   
3502  
3503  theorem forall_mem_of_forall_mem_union_right {p : α → Prop} {l₁ l₂ : list α}
id                                                                       └──┘ 
src                                                                       └──┘
typ                                                                      └──┘ 
3504     (h : ∀ x ∈ l₁ ∪ l₂, p x) : ∀ x ∈ l₂, p x :=
id                └┘  └┘            └┘   
src                   
typ               └┘  └┘            └┘   
3505  (forall_mem_union.1 h).2
id    └──────────────┘   
src   └──────────────┘    
typ   └──────────────┘   
3506  
3507  end union
3508  
3509  /- inter -/
3510  section inter
3511  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
3512  
3513  @[simp] theorem inter_nil (l : list α) : [] ∩ l = [] := rfl
id                                  └──┘     └┘    └┘    └─┘
src                                 └──┘      └┘     └┘    └─┘
typ                                 └──┘     └┘    └┘    └─┘
doc    └──┘
3514  
3515  @[simp] theorem inter_cons_of_mem {a : α} (l₁ : list α) {l₂ : list α} (h : a ∈ l₂) :
id                                                  └──┘         └──┘          └┘
src                                                  └──┘          └──┘           
typ                                                 └──┘         └──┘          └┘
doc    └──┘
3516    (a::l₁) ∩ l₂ = a :: (l₁ ∩ l₂) :=
id      └┘└┘   └┘   └┘  └┘  └┘
src      └┘           └┘     
typ     └┘└┘   └┘   └┘  └┘  └┘
3517  if_pos h
id   └────┘ 
src  └────┘
typ  └────┘ 
3518  
3519  @[simp] theorem inter_cons_of_not_mem {a : α} (l₁ : list α) {l₂ : list α} (h : a ∉ l₂) :
id                                                      └──┘         └──┘          └┘
src                                                      └──┘          └──┘           
typ                                                     └──┘         └──┘          └┘
doc    └──┘
3520    (a::l₁) ∩ l₂ = l₁ ∩ l₂ :=
id      └┘└┘   └┘  └┘  └┘
src      └┘            
typ     └┘└┘   └┘  └┘  └┘
3521  if_neg h
id   └────┘ 
src  └────┘
typ  └────┘ 
3522  
3523  theorem mem_of_mem_inter_left {l₁ l₂ : list α} {a : α} : a ∈ l₁ ∩ l₂ → a ∈ l₁ :=
id                                          └──┘              └┘  └┘     └┘
src                                         └──┘                            
typ                                         └──┘              └┘  └┘     └┘
3524  mem_of_mem_filter
id   └───────────────┘
src  └───────────────┘
typ  └───────────────┘
3525  
3526  theorem mem_of_mem_inter_right {l₁ l₂ : list α} {a : α} : a ∈ l₁ ∩ l₂ → a ∈ l₂ :=
id                                           └──┘              └┘  └┘     └┘
src                                          └──┘                            
typ                                          └──┘              └┘  └┘     └┘
3527  of_mem_filter
id   └───────────┘
src  └───────────┘
typ  └───────────┘
3528  
3529  theorem mem_inter_of_mem_of_mem {l₁ l₂ : list α} {a : α} : a ∈ l₁ → a ∈ l₂ → a ∈ l₁ ∩ l₂ :=
id                                            └──┘              └┘     └┘     └┘  └┘
src                                           └──┘                                    
typ                                           └──┘              └┘     └┘     └┘  └┘
3530  mem_filter_of_mem
id   └───────────────┘
src  └───────────────┘
typ  └───────────────┘
3531  
3532  @[simp] theorem mem_inter {a : α} {l₁ l₂ : list α} : a ∈ l₁ ∩ l₂ ↔ a ∈ l₁ ∧ a ∈ l₂ :=
id                                             └──┘       └┘  └┘    └┘    └┘
src                                             └──┘                          
typ                                            └──┘       └┘  └┘    └┘    └┘
doc    └──┘
3533  mem_filter
id   └────────┘
src  └────────┘
typ  └────────┘
3534  
3535  theorem inter_subset_left (l₁ l₂ : list α) : l₁ ∩ l₂ ⊆ l₁ :=
id                                      └──┘     └┘  └┘  └┘
src                                     └──┘             
typ                                     └──┘     └┘  └┘  └┘
3536  filter_subset _
id   └───────────┘
src  └───────────┘
typ  └───────────┘
3537  
3538  theorem inter_subset_right (l₁ l₂ : list α) : l₁ ∩ l₂ ⊆ l₂ :=
id                                       └──┘     └┘  └┘  └┘
src                                      └──┘             
typ                                      └──┘     └┘  └┘  └┘
3539  λ a, mem_of_mem_inter_right
id       └────────────────────┘
src       └────────────────────┘
typ      └────────────────────┘
3540  
3541  theorem subset_inter {l l₁ l₂ : list α} (h₁ : l ⊆ l₁) (h₂ : l ⊆ l₂) : l ⊆ l₁ ∩ l₂ :=
id                                   └──┘           └┘          └┘      └┘  └┘
src                                  └──┘                                      
typ                                  └──┘           └┘          └┘      └┘  └┘
3542  λ a h, mem_inter.2 ⟨h₁ h, h₂ h⟩
id        └───────┘   └┘   └┘ 
src         └───────┘
typ       └───────┘   └┘   └┘ 
3543  
3544  theorem inter_eq_nil_iff_disjoint {l₁ l₂ : list α} : l₁ ∩ l₂ = [] ↔ disjoint l₁ l₂ :=
id                                              └──┘     └┘  └┘  └┘  └──────┘ └┘ └┘
src                                             └──┘              └┘  └──────┘
typ                                             └──┘     └┘  └┘  └┘  └──────┘ └┘ └┘
doc                                                                      └──────┘
3545  by simp only [eq_nil_iff_forall_not_mem, mem_inter, not_and]; refl
id                 └───────────────────────┘  └───────┘  └─────┘
src     └─────────┘└───────────────────────┘└┘└───────┘└┘└─────┘  └────
typ     └─────────┘└───────────────────────┘└┘└───────┘└┘└─────┘  └────
doc     └─────────┘                         └┘         └┘         └────
txt     └─────────┘                         └┘         └┘         └────
par     └─────────┘                         └┘         └┘         └────
pid         └──┘└┘                         └┘         └┘             
st     └────────────────────────────────────────────────────────────────
3546  
src  
typ  
doc  
txt  
par  
pid  
st   
3547  theorem forall_mem_inter_of_forall_left {p : α → Prop} {l₁ : list α} (h : ∀ x ∈ l₁, p x)
id                                                               └──┘             └┘   
src                                                               └──┘
typ                                                              └──┘             └┘   
3548       (l₂ : list α) :
id              └──┘ 
src             └──┘
typ             └──┘ 
3549    ∀ x, x ∈ l₁ ∩ l₂ → p x :=
id           └┘  └┘    
src               
typ          └┘  └┘    
3550  ball.imp_left (λ x, mem_of_mem_inter_left) h
id   └───────────┘      └───────────────────┘  
src  └───────────┘       └───────────────────┘
typ  └───────────┘      └───────────────────┘  
3551  
3552  theorem forall_mem_inter_of_forall_right {p : α → Prop} (l₁ : list α) {l₂ : list α}
id                                                                └──┘         └──┘ 
src                                                                └──┘          └──┘
typ                                                               └──┘         └──┘ 
3553      (h : ∀ x ∈ l₂, p x) :
id                 └┘   
typ                └┘   
3554    ∀ x, x ∈ l₁ ∩ l₂ → p x :=
id           └┘  └┘    
src               
typ          └┘  └┘    
3555  ball.imp_left (λ x, mem_of_mem_inter_right) h
id   └───────────┘      └────────────────────┘  
src  └───────────┘       └────────────────────┘
typ  └───────────┘      └────────────────────┘  
3556  
3557  end inter
3558  
3559  /- bag_inter -/
3560  section bag_inter
3561  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
3562  
3563  @[simp] theorem nil_bag_inter (l : list α) : [].bag_inter l = [] :=
id                                      └──┘     └┘└───────┘    └┘
src                                     └──┘      └┘└───────┘     └┘
typ                                     └──┘     └┘└───────┘    └┘
doc    └──┘
3564  by cases l; refl
id            
src     └────┘   └────
typ     └────┘  └────
doc     └────┘   └────
txt     └────┘   └────
par     └────┘   └────
pid                 
st     └──────────────
3565  
src  
typ  
doc  
txt  
par  
pid  
st   
3566  @[simp] theorem bag_inter_nil (l : list α) : l.bag_inter [] = [] :=
id                                      └──┘     └────────┘ └┘  └┘
src                                     └──┘       └────────┘ └┘  └┘
typ                                     └──┘     └────────┘ └┘  └┘
doc    └──┘
3567  by cases l; refl
id            
src     └────┘   └────
typ     └────┘  └────
doc     └────┘   └────
txt     └────┘   └────
par     └────┘   └────
pid                 
st     └──────────────
3568  
src  
typ  
doc  
txt  
par  
pid  
st   
3569  @[simp] theorem cons_bag_inter_of_pos {a} (l₁ : list α) {l₂} (h : a ∈ l₂) :
id                                                   └──┘               └┘
src                                                  └──┘                
typ                                                  └──┘               └┘
doc    └──┘
3570    (a :: l₁).bag_inter l₂ = a :: l₁.bag_inter (l₂.erase a) :=
id       └┘ └┘ └───────┘  └┘   └┘ └┘└────────┘  └┘└────┘ 
src       └┘    └───────┘        └┘   └────────┘    └────┘
typ      └┘ └┘ └───────┘  └┘   └┘ └┘└────────┘  └┘└────┘ 
3571  by cases l₂; exact if_pos h
id            └┘        └────┘ 
src     └────┘    └────┘└────┘ 
typ     └────┘└┘  └────┘└────┘
doc     └────┘    └────┘       
txt     └────┘    └────┘       
par     └────┘    └────┘       
pid                          
st     └─────────────────────────
3572  
src  
typ  
doc  
txt  
par  
pid  
st   
3573  @[simp] theorem cons_bag_inter_of_neg {a} (l₁ : list α) {l₂} (h : a ∉ l₂) :
id                                                   └──┘               └┘
src                                                  └──┘                
typ                                                  └──┘               └┘
doc    └──┘
3574    (a :: l₁).bag_inter l₂ = l₁.bag_inter l₂ :=
id       └┘ └┘ └───────┘  └┘  └┘└────────┘ └┘
src       └┘    └───────┘        └────────┘
typ      └┘ └┘ └───────┘  └┘  └┘└────────┘ └┘
3575  begin
st   └─────
3576    cases l₂, {simp only [bag_inter_nil]},
id           └┘              └───────────┘
src    └────┘     └─────────┘└───────────┘
typ    └────┘└┘   └─────────┘└───────────┘
doc    └────┘     └─────────┘             
txt    └────┘     └─────────┘             
par    └────┘     └─────────┘             
pid                  └──┘└┘             
st   ─────────┘└──────────────────────────┘└┘
3577    simp only [erase_of_not_mem h, list.bag_inter, if_neg h]
id                └──────────────┘   └────────────┘  └────┘ 
src    └─────────┘└──────────────┘ └┘└────────────┘└┘└────┘ └┘
typ    └─────────┘└──────────────┘└┘└────────────┘└┘└────┘└┘
doc    └─────────┘                 └┘              └┘       └┘
txt    └─────────┘                 └┘              └┘       └┘
par    └─────────┘                 └┘              └┘       └┘
pid        └──┘└┘                 └┘              └┘       
st   ──────────────────────────────────────────────────────────┘
3578  end
st   └─┘
3579  
3580  @[simp] theorem mem_bag_inter {a : α} : ∀ {l₁ l₂ : list α}, a ∈ l₁.bag_inter l₂ ↔ a ∈ l₁ ∧ a ∈ l₂
id                                                    └──┘      └┘└────────┘ └┘    └┘    └┘
src                                                     └──┘          └────────┘              
typ                                                   └──┘      └┘└────────┘ └┘    └┘    └┘
doc    └──┘
3581  | []      l₂ := by simp only [nil_bag_inter, not_mem_nil, false_and]
id     └┘                          └───────────┘  └─────────┘  └───────┘
src    └┘               └─────────┘└───────────┘└┘└─────────┘└┘└───────┘└┘
typ    └┘               └─────────┘└───────────┘└┘└─────────┘└┘└───────┘└┘
doc                     └─────────┘             └┘           └┘         └┘
txt                     └─────────┘             └┘           └┘         └┘
par                     └─────────┘             └┘           └┘         └┘
pid                         └──┘└┘             └┘           └┘         
st                     └─────────────────────────────────────────────────┘
3582  | (b::l₁) l₂ := begin
id       └┘
src      └┘
typ      └┘
st                   └─────
3583      by_cases b ∈ l₂,
id                  └┘
src      └───────┘ 
typ      └───────┘└┘
doc      └───────┘  
txt      └───────┘  
par      └───────┘  
pid                
st   ──────────────────┘└─
3584      { rw [cons_bag_inter_of_pos _ h, mem_cons_iff, mem_cons_iff, mem_bag_inter],
id             └───────────────────┘     └──────────┘  └──────────┘
src        └──┘└───────────────────┘└─┘ └┘└──────────┘└┘└──────────┘└┘             
typ        └──┘└───────────────────┘└─┘└┘└──────────┘└┘└──────────┘└┘└───────────┘
doc        └──┘                     └─┘ └┘            └┘            └┘             
txt        └──┘                     └─┘ └┘            └┘            └┘             
par        └──┘                     └─┘ └┘            └┘            └┘             
pid          └┘                     └─┘ └┘            └┘            └┘             
st   ─────┘└───────────────────────────┘└────────────┘└────────────┘└─────────────┘└──
3585        by_cases ba : a = b,
id                         
src        └───────┘  └─┘ 
typ        └───────┘  └─┘
doc        └───────┘  └─┘  
txt        └───────┘  └─┘  
par        └───────┘  └─┘  
pid                  └─┘  
st   ────────────────────────┘└─
3586        { simp only [ba, h, eq_self_iff_true, true_or, true_and] },
id                      └┘    └──────────────┘  └─────┘  └──────┘
src          └─────────┘  └┘ └┘└──────────────┘└┘└─────┘└┘└──────┘└┘
typ          └─────────┘└┘└┘└┘└──────────────┘└┘└─────┘└┘└──────┘└┘
doc          └─────────┘  └┘ └┘                └┘       └┘        └┘
txt          └─────────┘  └┘ └┘                └┘       └┘        └┘
par          └─────────┘  └┘ └┘                └┘       └┘        └┘
pid              └──┘└┘  └┘ └┘                └┘       └┘        
st   ───────┘└─────────────────────────────────────────────────────┘└┘
3587        { simp only [mem_erase_of_ne ba, ba, false_or] } },
id                      └─────────────┘ └┘  └┘  └──────┘
src          └─────────┘└─────────────┘  └┘  └┘└──────┘└┘
typ          └─────────┘└─────────────┘└┘└┘└┘└┘└──────┘└┘
doc          └─────────┘                 └┘  └┘        └┘
txt          └─────────┘                 └┘  └┘        └┘
par          └─────────┘                 └┘  └┘        └┘
pid              └──┘└┘                 └┘  └┘        
st   ────────────────────────────────────────────────────┘└──┘
3588      { rw [cons_bag_inter_of_neg _ h, mem_bag_inter, mem_cons_iff, or_and_distrib_right],
id             └───────────────────┘                    └──────────┘  └──────────────────┘
src        └──┘└───────────────────┘└─┘ └┘             └┘└──────────┘└┘└──────────────────┘
typ        └──┘└───────────────────┘└─┘└┘└───────────┘└┘└──────────┘└┘└──────────────────┘
doc        └──┘                     └─┘ └┘             └┘            └┘                    
txt        └──┘                     └─┘ └┘             └┘            └┘                    
par        └──┘                     └─┘ └┘             └┘            └┘                    
pid          └┘                     └─┘ └┘             └┘            └┘                    
st   ──────────────────────────────────┘└─────────────┘└────────────┘└────────────────────┘└──
3589        symmetry, apply or_iff_right_of_imp,
id                         └─────────────────┘
src        └──────┘  └────┘└─────────────────┘
typ        └──────┘  └────┘└─────────────────┘
doc        └──────┘  └────┘
txt        └──────┘  └────┘
par        └──────┘  └────┘
pid                       
st   ─────────────┘└─────────────────────────┘└─
3590        rintro ⟨rfl, h'⟩, exact h.elim h' }
id                                 └────┘ └┘
src        └──────────────┘  └────┘└────┘  
typ        └──────────────┘  └────┘└────┘└┘
doc        └──────────────┘  └────┘        
txt        └──────────────┘  └────┘        
par        └──────────────┘  └────┘        
pid              └────────┘               
st   ─────────────────────┘└────────────────┘└─
3591    end
st   ────┘
3592  
3593  @[simp] theorem count_bag_inter {a : α} :
id                                        
typ                                       
doc    └──┘
3594    ∀ {l₁ l₂ : list α}, count a (l₁.bag_inter l₂) = min (count a l₁) (count a l₂)
id               └──┘    └───┘   └┘└────────┘ └┘   └─┘  └───┘  └┘   └───┘  └┘
src               └──┘     └───┘      └────────┘      └─┘  └───┘        └───┘
typ              └──┘    └───┘   └┘└────────┘ └┘   └─┘  └───┘  └┘   └───┘  └┘
doc                        └───┘                            └───┘        └───┘
3595  | []         l₂ := by simp
id     └┘
src    └┘                  └───┘
typ    └┘                  └───┘
doc                        └───┘
txt                        └───┘
par                        └───┘
pid                            
st                        └────┘
3596  | l₁         [] := by simp
id                └┘
src               └┘       └───┘
typ               └┘       └───┘
doc                        └───┘
txt                        └───┘
par                        └───┘
pid                            
st                        └────┘
3597  | (h₁ :: l₁) (h₂ :: l₂) :=
id         └┘         └┘
src        └┘         └┘
typ        └┘         └┘
3598  begin
st   └─────
3599    simp only [list.bag_inter, list.mem_cons_iff],
id                └────────────┘  └───────────────┘
src    └─────────┘└────────────┘└┘└───────────────┘
typ    └─────────┘└────────────┘└┘└───────────────┘
doc    └─────────┘              └┘                 
txt    └─────────┘              └┘                 
par    └─────────┘              └┘                 
pid        └──┘└┘              └┘                 
st   ──────────────────────────────────────────────┘└─
3600    by_cases p₁ : h₂ = h₁; by_cases p₂ : h₁ = a,
id                   └┘  └┘                └┘   
src    └───────┘  └─┘      └───────┘  └─┘   
typ    └───────┘  └─┘└┘└┘  └───────┘  └─┘└┘ 
doc    └───────┘  └─┘       └───────┘  └─┘   
txt    └───────┘  └─┘       └───────┘  └─┘   
par    └───────┘  └─┘       └───────┘  └─┘   
pid              └─┘                 └─┘   
st   ────────────────────────────────────────────┘└─
3601    { simp only [p₁, p₂, count_bag_inter, min_succ_succ, erase_cons_head, if_true, mem_cons_iff,
id                  └┘  └┘                   └───────────┘  └─────────────┘  └─────┘  └──────────┘
src      └─────────┘  └┘  └┘               └┘└───────────┘└┘└─────────────┘└┘└─────┘└┘└──────────┘└─
typ      └─────────┘└┘└┘└┘└┘└─────────────┘└┘└───────────┘└┘└─────────────┘└┘└─────┘└┘└──────────┘└─
doc      └─────────┘  └┘  └┘               └┘             └┘               └┘       └┘            └─
txt      └─────────┘  └┘  └┘               └┘             └┘               └┘       └┘            └─
par      └─────────┘  └┘  └┘               └┘             └┘               └┘       └┘            └─
pid          └──┘└┘  └┘  └┘               └┘             └┘               └┘       └┘            └─
st   ───┘└──────────────────────────────────────────────────────────────────────────────────────────
3602                 count_cons_self, true_or, eq_self_iff_true] },
id                  └─────────────┘  └─────┘  └──────────────┘
src  ──────────────┘└─────────────┘└┘└─────┘└┘└──────────────┘└┘
typ  ──────────────┘└─────────────┘└┘└─────┘└┘└──────────────┘└┘
doc  ──────────────┘               └┘       └┘                └┘
txt  ──────────────┘               └┘       └┘                └┘
par  ──────────────┘               └┘       └┘                └┘
pid  ──────────────┘               └┘       └┘                
st   ──────────────────────────────────────────────────────────┘└┘
3603    { simp only [p₁, ne.symm p₂, count_bag_inter, count_cons, erase_cons_head, if_true, mem_cons_iff,
id                  └┘  └─────┘ └┘                   └────────┘  └─────────────┘  └─────┘  └──────────┘
src      └─────────┘  └┘└─────┘  └┘               └┘└────────┘└┘└─────────────┘└┘└─────┘└┘└──────────┘└─
typ      └─────────┘└┘└┘└─────┘└┘└┘└─────────────┘└┘└────────┘└┘└─────────────┘└┘└─────┘└┘└──────────┘└─
doc      └─────────┘  └┘         └┘               └┘          └┘               └┘       └┘            └─
txt      └─────────┘  └┘         └┘               └┘          └┘               └┘       └┘            └─
par      └─────────┘  └┘         └┘               └┘          └┘               └┘       └┘            └─
pid          └──┘└┘  └┘         └┘               └┘          └┘               └┘       └┘            └─
st   ───┘└───────────────────────────────────────────────────────────────────────────────────────────────
3604                 true_or, eq_self_iff_true, if_false] },
id                  └─────┘  └──────────────┘  └──────┘
src  ──────────────┘└─────┘└┘└──────────────┘└┘└──────┘└┘
typ  ──────────────┘└─────┘└┘└──────────────┘└┘└──────┘└┘
doc  ──────────────┘       └┘                └┘        └┘
txt  ──────────────┘       └┘                └┘        └┘
par  ──────────────┘       └┘                └┘        └┘
pid  ──────────────┘       └┘                └┘        
st   ───────────────────────────────────────────────────┘└┘
3605    { rw p₂ at p₁,
id          └┘
src      └─┘  └────┘
typ      └─┘└┘└────┘
doc      └─┘  └────┘
txt      └─┘  └────┘
par      └─┘  └────┘
pid          └────┘
st   ───┘└─────────┘└─
3606      by_cases p₃ : a ∈ l₂,
id                       └┘
src      └───────┘  └─┘ 
typ      └───────┘  └─┘└┘
doc      └───────┘  └─┘  
txt      └───────┘  └─┘  
par      └───────┘  └─┘  
pid                └─┘  
st   ───────────────────────┘└─
3607      { simp only [p₁, ne.symm p₁, p₂, p₃, erase_cons, count_bag_inter, eq.symm (min_succ_succ _ _),
id                    └┘  └─────┘ └┘  └┘  └┘  └────────┘                   └─────┘  └───────────┘
src        └─────────┘  └┘└─────┘  └┘  └┘  └┘└────────┘└┘               └┘└─────┘ └───────────┘└──────
typ        └─────────┘└┘└┘└─────┘└┘└┘└┘└┘└┘└┘└────────┘└┘└─────────────┘└┘└─────┘ └───────────┘└──────
doc        └─────────┘  └┘         └┘  └┘  └┘          └┘               └┘                     └──────
txt        └─────────┘  └┘         └┘  └┘  └┘          └┘               └┘                     └──────
par        └─────────┘  └┘         └┘  └┘  └┘          └┘               └┘                     └──────
pid            └──┘└┘  └┘         └┘  └┘  └┘          └┘               └┘                     └──────
st   ─────┘└────────────────────────────────────────────────────────────────────────────────────────────
3608                   succ_pred_eq_of_pos (count_pos.2 p₃), if_true, mem_cons_iff, false_or,
id                    └─────────────────┘  └───────┘   └┘   └─────┘  └──────────┘  └──────┘
src  ────────────────┘└─────────────────┘ └───────┘└─┘  └─┘└─────┘└┘└──────────┘└┘└──────┘└─
typ  ────────────────┘└─────────────────┘ └───────┘└─┘└┘└─┘└─────┘└┘└──────────┘└┘└──────┘└─
doc  ────────────────┘                             └─┘  └─┘       └┘            └┘        └─
txt  ────────────────┘                             └─┘  └─┘       └┘            └┘        └─
par  ────────────────┘                             └─┘  └─┘       └┘            └┘        └─
pid  ────────────────┘                             └─┘  └─┘       └┘            └┘        └─
st   ────────────────────────────────────────────────────────────────────────────────────────
3609                   count_cons_self, eq_self_iff_true, if_false, ne.def, not_false_iff,
id                    └─────────────┘  └──────────────┘  └──────┘  └────┘  └───────────┘
src  ────────────────┘└─────────────┘└┘└──────────────┘└┘└──────┘└┘└────┘└┘└───────────┘└─
typ  ────────────────┘└─────────────┘└┘└──────────────┘└┘└──────┘└┘└────┘└┘└───────────┘└─
doc  ────────────────┘               └┘                └┘        └┘      └┘             └─
txt  ────────────────┘               └┘                └┘        └┘      └┘             └─
par  ────────────────┘               └┘                └┘        └┘      └┘             └─
pid  ────────────────┘               └┘                └┘        └┘      └┘             └─
st   ─────────────────────────────────────────────────────────────────────────────────────
3610                   count_erase_self, list.count_cons_of_ne] },
id                    └──────────────┘  └───────────────────┘
src  ────────────────┘└──────────────┘└┘└───────────────────┘└┘
typ  ────────────────┘└──────────────┘└┘└───────────────────┘└┘
doc  ────────────────┘                └┘                     └┘
txt  ────────────────┘                └┘                     └┘
par  ────────────────┘                └┘                     └┘
pid  ────────────────┘                └┘                     
st   ─────────────────────────────────────────────────────────┘└┘
3611      { simp [ne.symm p₁, p₂, p₃] } },
id               └─────┘ └┘  └┘  └┘
src        └────┘└─────┘  └┘  └┘  └┘
typ        └────┘└─────┘└┘└┘└┘└┘└┘└┘
doc        └────┘         └┘  └┘  └┘
txt        └────┘         └┘  └┘  └┘
par        └────┘         └┘  └┘  └┘
pid                     └┘  └┘  
st   ───────────────────────────────┘└──┘
3612    { by_cases p₄ : h₁ ∈ l₂; simp only [ne.symm p₁, ne.symm p₂, p₄, count_bag_inter, if_true, if_false,
id                     └┘   └┘             └─────┘ └┘  └─────┘ └┘  └┘                   └─────┘  └──────┘
src      └───────┘  └─┘       └─────────┘└─────┘  └┘└─────┘  └┘  └┘               └┘└─────┘└┘└──────┘└─
typ      └───────┘  └─┘└┘ └┘  └─────────┘└─────┘└┘└┘└─────┘└┘└┘└┘└┘└─────────────┘└┘└─────┘└┘└──────┘└─
doc      └───────┘  └─┘       └─────────┘         └┘         └┘  └┘               └┘       └┘        └─
txt      └───────┘  └─┘       └─────────┘         └┘         └┘  └┘               └┘       └┘        └─
par      └───────┘  └─┘       └─────────┘         └┘         └┘  └┘               └┘       └┘        └─
pid                └─┘           └──┘└┘         └┘         └┘  └┘               └┘       └┘        └─
st   ──────────────────────────────────────────────────────────────────────────────────────────────────────
3613        mem_cons_iff, false_or, eq_self_iff_true, ne.def, not_false_iff,count_erase_of_ne, count_cons_of_ne] }
id         └──────────┘  └──────┘  └──────────────┘  └────┘  └───────────┘ └───────────────┘  └──────────────┘
src  ─────┘└──────────┘└┘└──────┘└┘└──────────────┘└┘└────┘└┘└───────────┘└───────────────┘└┘└──────────────┘└┘
typ  ─────┘└──────────┘└┘└──────┘└┘└──────────────┘└┘└────┘└┘└───────────┘└───────────────┘└┘└──────────────┘└┘
doc  ─────┘            └┘        └┘                └┘      └┘                              └┘                └┘
txt  ─────┘            └┘        └┘                └┘      └┘                              └┘                └┘
par  ─────┘            └┘        └┘                └┘      └┘                              └┘                └┘
pid  ─────┘            └┘        └┘                └┘      └┘                              └┘                
st   ──────────────────────────────────────────────────────────────────────────────────────────────────────────┘└─
3614  end
st   ──┘
3615  
3616  theorem bag_inter_sublist_left : ∀ l₁ l₂ : list α, l₁.bag_inter l₂ <+ l₁
id                                      └┘      └──┘   └┘└────────┘ └┘ └┘ └┘
src                                             └──┘      └────────┘    └┘
typ                                     └┘      └──┘   └┘└────────┘ └┘ └┘ └┘
3617  | []      l₂ := by simp [nil_sublist]
id     └┘                     └─────────┘
src    └┘               └────┘└─────────┘└┘
typ    └┘               └────┘└─────────┘└┘
doc                     └────┘           └┘
txt                     └────┘           └┘
par                     └────┘           └┘
pid                                    
st                     └──────────────────┘
3618  | (b::l₁) l₂ := begin
id       └┘
src      └┘
typ      └┘
st                   └─────
3619    by_cases b ∈ l₂; simp [h],
id                └┘        
src    └───────┘     └────┘ 
typ    └───────┘└┘  └────┘
doc    └───────┘      └────┘ 
txt    └───────┘      └────┘ 
par    └───────┘      └────┘ 
pid                       
st   ──────────────────────────┘└─
3620    { apply cons_sublist_cons, apply bag_inter_sublist_left },
id             └───────────────┘
src      └────┘└───────────────┘  └────┘                      
typ      └────┘└───────────────┘  └────┘                      
doc      └────┘                   └────┘                      
txt      └────┘                   └────┘                      
par      └────┘                   └────┘                      
pid                                                         
st   ───┘└─────────────────────┘└─────────────────────────────┘└┘
3621    { apply sublist_cons_of_sublist, apply bag_inter_sublist_left }
id             └─────────────────────┘
src      └────┘└─────────────────────┘  └────┘                      
typ      └────┘└─────────────────────┘  └────┘                      
doc      └────┘                         └────┘                      
txt      └────┘                         └────┘                      
par      └────┘                         └────┘                      
pid                                                               
st   ────────────────────────────────┘└─────────────────────────────┘└─
3622  end
st   ──┘
3623  
3624  theorem bag_inter_nil_iff_inter_nil : ∀ l₁ l₂ : list α, l₁.bag_inter l₂ = [] ↔ l₁ ∩ l₂ = []
id                                           └┘      └──┘   └┘└────────┘ └┘  └┘  └┘  └┘  └┘
src                                                  └──┘      └────────┘     └┘          └┘
typ                                          └┘      └──┘   └┘└────────┘ └┘  └┘  └┘  └┘  └┘
3625  | []      l₂ := by simp
id     └┘
src    └┘               └───┘
typ    └┘               └───┘
doc                     └───┘
txt                     └───┘
par                     └───┘
pid                         
st                     └────┘
3626  | (b::l₁) l₂ :=
id       └┘
src      └┘
typ      └┘
3627  begin
st   └─────
3628    by_cases h : b ∈ l₂; simp [h],
id                    └┘        
src    └───────┘ └─┘     └────┘ 
typ    └───────┘ └─┘└┘  └────┘
doc    └───────┘ └─┘      └────┘ 
txt    └───────┘ └─┘      └────┘ 
par    └───────┘ └─┘      └────┘ 
pid             └─┘           
st   ──────────────────────────────┘└─
3629    exact bag_inter_nil_iff_inter_nil l₁ l₂
id           └─────────────────────────┘ └┘ └┘
src    └────┘                               
typ    └────┘└─────────────────────────┘└┘└┘
doc    └────┘                               
txt    └────┘                               
par    └────┘                               
pid                                        
st   ─────────────────────────────────────────┘
3630  end
st   └─┘
3631  
3632  end bag_inter
3633  
3634  /- pairwise relation (generalized no duplicate) -/
3635  
3636  section pairwise
3637  
3638  run_cmd tactic.mk_iff_of_inductive_prop `list.pairwise `list.pairwise_iff
id           └─────────────────────────────┘               
src          └─────────────────────────────┘               
typ          └─────────────────────────────┘               
doc          └─────────────────────────────┘
3639  
3640  variable {R : α → α → Prop}
id            
typ           
3641  
3642  theorem rel_of_pairwise_cons {a : α} {l : list α}
id                                            └──┘ 
src                                            └──┘
typ                                           └──┘ 
3643    (p : pairwise R (a::l)) : ∀ {a'}, a' ∈ l → R a a' :=
id          └──────┘   └┘        └┘   └┘       └┘
src         └──────┘     └┘                 
typ         └──────┘   └┘        └┘   └┘       └┘
doc         └──────┘
3644  (pairwise_cons.1 p).1
id    └───────────┘   
src   └───────────┘    
typ   └───────────┘   
3645  
3646  theorem pairwise_of_pairwise_cons {a : α} {l : list α}
id                                                 └──┘ 
src                                                 └──┘
typ                                                └──┘ 
3647    (p : pairwise R (a::l)) : pairwise R l :=
id          └──────┘   └┘     └──────┘  
src         └──────┘     └┘      └──────┘
typ         └──────┘   └┘     └──────┘  
doc         └──────┘             └──────┘
3648  (pairwise_cons.1 p).2
id    └───────────┘   
src   └───────────┘    
typ   └───────────┘   
3649  
3650  theorem pairwise.imp_of_mem {S : α → α → Prop} {l : list α}
id                                                     └──┘ 
src                                                      └──┘
typ                                                    └──┘ 
3651    (H : ∀ {a b}, a ∈ l → b ∈ l → R a b → S a b) (p : pairwise R l) : pairwise S l :=
id                                         └──────┘      └──────┘  
src                                                    └──────┘        └──────┘
typ                                        └──────┘      └──────┘  
doc                                                      └──────┘        └──────┘
3652  begin
st   └─────
3653    induction p with a l r p IH generalizing H; constructor,
id               
src    └────────┘ └─────────────────────────────┘  └─────────┘
typ    └────────┘└─────────────────────────────┘  └─────────┘
doc    └────────┘ └─────────────────────────────┘  └─────────┘
txt    └────────┘ └─────────────────────────────┘  └─────────┘
par    └────────┘ └─────────────────────────────┘  └─────────┘
pid              └─────────────┘└─────────────┘
st   ────────────────────────────────────────────────────────┘└─
3654    { exact ball.imp_right
id             └────────────┘
src      └────┘└────────────┘
typ      └────┘└────────────┘
doc      └────┘              
txt      └────┘              
par      └────┘              
pid                         
st   ───┘└────────────────────
3655        (λ x h, H (mem_cons_self _ _) (mem_cons_of_mem _ h)) r },
id                   └───────────┘       └─────────────┘       
src  ─────┘  └────┘  └───────────┘└────┘ └─────────────┘└─┘ └─┘ 
typ  ─────┘  └────┘ └───────────┘└────┘ └─────────────┘└─┘ └─┘
doc  ─────┘  └────┘               └────┘                └─┘ └─┘ 
txt  ─────┘  └────┘               └────┘                └─┘ └─┘ 
par  ─────┘  └────┘               └────┘                └─┘ └─┘ 
pid  ─────┘  └────┘               └────┘                └─┘ └─┘ 
st   ────────────────────────────────────────────────────────────┘└┘
3656    { exact IH (λ a b m m', H
id             └┘              
src      └────┘    └─────────┘ 
typ      └────┘└┘  └─────────┘
doc      └────┘    └─────────┘ 
txt      └────┘    └─────────┘ 
par      └────┘    └─────────┘ 
pid               └─────────┘ 
st   ────────────────────────────
3657        (mem_cons_of_mem _ m) (mem_cons_of_mem _ m')) }
id                                └─────────────┘
src  ─────┘                └─┘ └┘ └─────────────┘└─┘  └─┘
typ  ─────┘                └─┘ └┘ └─────────────┘└─┘  └─┘
doc  ─────┘                └─┘ └┘                └─┘  └─┘
txt  ─────┘                └─┘ └┘                └─┘  └─┘
par  ─────┘                └─┘ └┘                └─┘  └─┘
pid  ─────┘                └─┘ └┘                └─┘  └┘
st   ───────────────────────────────────────────────────┘└─
3658  end
st   ──┘
3659  
3660  theorem pairwise.imp {S : α → α → Prop}
id                                
typ                               
3661    (H : ∀ a b, R a b → S a b) {l : list α} : pairwise R l → pairwise S l :=
id                             └──┘     └──────┘     └──────┘  
src                                    └──┘      └──────┘       └──────┘
typ                            └──┘     └──────┘     └──────┘  
doc                                              └──────┘       └──────┘
3662  pairwise.imp_of_mem (λ a b _ _, H a b)
id   └─────────────────┘           
src  └─────────────────┘
typ  └─────────────────┘           
3663  
3664  theorem pairwise.and {S : α → α → Prop} {l : list α} :
id                                              └──┘ 
src                                               └──┘
typ                                             └──┘ 
3665    pairwise (λ a b, R a b ∧ S a b) l ↔ pairwise R l ∧ pairwise S l :=
id     └──────┘                 └──────┘    └──────┘  
src    └──────┘                          └──────┘      └──────┘
typ    └──────┘                 └──────┘    └──────┘  
doc    └──────┘                            └──────┘       └──────┘
3666  ⟨λ h, ⟨h.imp (λ a b h, h.1), h.imp (λ a b h, h.2)⟩,
id         └──┘            └──┘        
src          └──┘                 └──┘            
typ        └──┘            └──┘        
3667   λ ⟨hR, hS⟩, begin
id      
typ     
st                └─────
3668    clear_, induction hR with a l R1 R2 IH;
id                       └┘
src    └────┘  └────────┘  └────────────────┘
typ    └────┘  └────────┘└┘└────────────────┘
doc    └────┘  └────────┘  └────────────────┘
txt    └────┘  └────────┘  └────────────────┘
par    └────┘  └────────┘  └────────────────┘
pid                       └───────────────┘
st   ───────┘└─────────────────────────────────
3669    simp only [pairwise.nil, pairwise_cons] at *,
id                └──────────┘  └───────────┘
src    └─────────┘└──────────┘└┘└───────────┘└────┘
typ    └─────────┘└──────────┘└┘└───────────┘└────┘
doc    └─────────┘            └┘             └────┘
txt    └─────────┘            └┘             └────┘
par    └─────────┘            └┘             └────┘
pid        └──┘└┘            └┘             └──┘
st   ─────────────────────────────────────────────┘└─
3670    exact ⟨λ b bl, ⟨R1 b bl, hS.1 b bl⟩, IH hS.2⟩
id                     └┘                   └┘ └┘
src    └────┘  └─────┘      └┘  └─┘   └─┘    └───
typ    └────┘  └─────┘ └┘   └┘  └─┘   └─┘└┘└┘└───
doc    └────┘  └─────┘      └┘  └─┘   └─┘    └───
txt    └────┘  └─────┘      └┘  └─┘   └─┘    └───
par    └────┘  └─────┘      └┘  └─┘   └─┘    └───
pid           └─────┘      └┘  └─┘   └─┘    └─┘
st   ────────────────────────────────────────────────
3671   end⟩
src  
typ  
doc  
txt  
par  
pid  
st   └─┘
3672  
3673  theorem pairwise.imp₂ {S : α → α → Prop} {T : α → α → Prop}
id                                                  
typ                                                 
3674    (H : ∀ a b, R a b → S a b → T a b) {l : list α}
id                                  └──┘ 
src                                            └──┘
typ                                 └──┘ 
3675    (hR : pairwise R l) (hS : pairwise S l) : pairwise T l :=
id           └──────┘          └──────┘      └──────┘  
src          └──────┘            └──────┘        └──────┘
typ          └──────┘          └──────┘      └──────┘  
doc          └──────┘            └──────┘        └──────┘
3676  (pairwise.and.2 ⟨hR, hS⟩).imp $ λ a b, and.rec (H a b)
id    └──────────┘   └┘  └┘  └─┘         └─────┘    
src   └──────────┘           └─┘           └─────┘
typ   └──────────┘   └┘  └┘  └─┘         └─────┘    
3677  
3678  theorem pairwise.iff_of_mem {S : α → α → Prop} {l : list α}
id                                                     └──┘ 
src                                                      └──┘
typ                                                    └──┘ 
3679    (H : ∀ {a b}, a ∈ l → b ∈ l → (R a b ↔ S a b)) : pairwise R l ↔ pairwise S l :=
id                                       └──────┘    └──────┘  
src                                                  └──────┘      └──────┘
typ                                      └──────┘    └──────┘  
doc                                                     └──────┘       └──────┘
3680  ⟨pairwise.imp_of_mem (λ a b m m', (H m m').1),
id    └─────────────────┘       └┘     └┘ 
src   └─────────────────┘                      
typ   └─────────────────┘       └┘     └┘ 
3681   pairwise.imp_of_mem (λ a b m m', (H m m').2)⟩
id    └─────────────────┘       └┘     └┘ 
src   └─────────────────┘                      
typ   └─────────────────┘       └┘     └┘ 
3682  
3683  theorem pairwise.iff {S : α → α → Prop}
id                                
typ                               
3684    (H : ∀ a b, R a b ↔ S a b) {l : list α} : pairwise R l ↔ pairwise S l :=
id                            └──┘     └──────┘    └──────┘  
src                                   └──┘      └──────┘      └──────┘
typ                           └──┘     └──────┘    └──────┘  
doc                                              └──────┘       └──────┘
3685  pairwise.iff_of_mem (λ a b _ _, H a b)
id   └─────────────────┘           
src  └─────────────────┘
typ  └─────────────────┘           
3686  
3687  theorem pairwise_of_forall {l : list α} (H : ∀ x y, R x y) : pairwise R l :=
id                                   └──┘                   └──────┘  
src                                  └──┘                         └──────┘
typ                                  └──┘                   └──────┘  
doc                                                               └──────┘
3688  by induction l; [exact pairwise.nil,
id                        └──────────┘
src     └────────┘   └────┘└──────────┘
typ     └────────┘  └────┘└──────────┘
doc     └────────┘    └────┘
txt     └────────┘    └────┘
par     └────────┘    └────┘
pid                       
st     └──────────────────────────────────
3689  simp only [*, pairwise_cons, forall_2_true_iff, and_true]]
id                 └───────────┘  └───────────────┘  └──────┘
src  └────────────┘└───────────┘└┘└───────────────┘└┘└──────┘
typ  └────────────┘└───────────┘└┘└───────────────┘└┘└──────┘
doc  └────────────┘             └┘                 └┘        
txt  └────────────┘             └┘                 └┘        
par  └────────────┘             └┘                 └┘        
pid      └──┘└───┘             └┘                 └┘        
st   ─────────────────────────────────────────────────────────┘
3690  
3691  theorem pairwise.and_mem {l : list α} :
id                                 └──┘ 
src                                └──┘
typ                                └──┘ 
3692    pairwise R l ↔ pairwise (λ x y, x ∈ l ∧ y ∈ l ∧ R x y) l :=
id     └──────┘    └──────┘                   
src    └──────┘      └──────┘                    
typ    └──────┘    └──────┘                   
doc    └──────┘       └──────┘
3693  pairwise.iff_of_mem (by simp only [true_and, iff_self, forall_2_true_iff] {contextual := tt})
id   └─────────────────┘                └──────┘  └──────┘  └───────────────┘                 └┘
src  └─────────────────┘     └─────────┘└──────┘└┘└──────┘└┘└───────────────┘└┘ └────────────┘└┘
typ  └─────────────────┘     └─────────┘└──────┘└┘└──────┘└┘└───────────────┘└┘ └────────────┘└┘
doc                          └─────────┘        └┘        └┘                 └┘ └────────────┘  
txt                          └─────────┘        └┘        └┘                 └┘ └────────────┘  
par                          └─────────┘        └┘        └┘                 └┘ └────────────┘  
pid                              └──┘└┘        └┘        └┘                  └────────────┘  
st                          └───────────────────────────────────────────────────────────────────┘
3694  
3695  theorem pairwise.imp_mem {l : list α} :
id                                 └──┘ 
src                                └──┘
typ                                └──┘ 
3696    pairwise R l ↔ pairwise (λ x y, x ∈ l → y ∈ l → R x y) l :=
id     └──────┘    └──────┘                     
src    └──────┘      └──────┘                  
typ    └──────┘    └──────┘                     
doc    └──────┘       └──────┘
3697  pairwise.iff_of_mem (by simp only [forall_prop_of_true, iff_self, forall_2_true_iff] {contextual := tt})
id   └─────────────────┘                └─────────────────┘  └──────┘  └───────────────┘                 └┘
src  └─────────────────┘     └─────────┘└─────────────────┘└┘└──────┘└┘└───────────────┘└┘ └────────────┘└┘
typ  └─────────────────┘     └─────────┘└─────────────────┘└┘└──────┘└┘└───────────────┘└┘ └────────────┘└┘
doc                          └─────────┘                   └┘        └┘                 └┘ └────────────┘  
txt                          └─────────┘                   └┘        └┘                 └┘ └────────────┘  
par                          └─────────┘                   └┘        └┘                 └┘ └────────────┘  
pid                              └──┘└┘                   └┘        └┘                  └────────────┘  
st                          └──────────────────────────────────────────────────────────────────────────────┘
3698  
3699  theorem pairwise_of_sublist : Π {l₁ l₂ : list α}, l₁ <+ l₂ → pairwise R l₂ → pairwise R l₁
id                                           └──┘    └┘ └┘ └┘   └──────┘  └┘   └──────┘  └┘
src                                           └──┘        └┘      └──────┘        └──────┘
typ                                          └──┘    └┘ └┘ └┘   └──────┘  └┘   └──────┘  └┘
doc                                                               └──────┘        └──────┘
3700  | ._ ._ sublist.slnil h := h
id           └───────────┘ 
src          └───────────┘
typ          └───────────┘ 
3701  | ._ ._ (sublist.cons l₁ l₂ a s) (pairwise.cons i n) := pairwise_of_sublist s n
id            └──────────┘            └───────────┘        └─────────────────┘
src           └──────────┘             └───────────┘
typ           └──────────┘            └───────────┘        └─────────────────┘
3702  | ._ ._ (sublist.cons2 l₁ l₂ a s) (pairwise.cons i n) :=
id            └───────────┘            └───────────┘  
src           └───────────┘             └───────────┘
typ           └───────────┘            └───────────┘  
3703    (pairwise_of_sublist s n).cons (ball.imp_left (subset_of_sublist s) i)
id      └─────────────────┘     └──┘   └───────────┘  └───────────────┘
src                             └──┘   └───────────┘  └───────────────┘
typ     └─────────────────┘     └──┘   └───────────┘  └───────────────┘
3704  
3705  theorem forall_of_forall_of_pairwise (H : symmetric R)
id                                             └───────┘ 
src                                            └───────┘
typ                                            └───────┘ 
3706    {l : list α} (H₁ : ∀ x ∈ l, R x x) (H₂ : pairwise R l) :
id          └──┘                          └──────┘  
src         └──┘                                └──────┘
typ         └──┘                          └──────┘  
doc                                             └──────┘
3707    ∀ (x ∈ l) (y ∈ l), R x y :=
id                     
typ                    
3708  begin
st   └─────
3709    induction l with a l IH, { exact forall_mem_nil _ },
id                                     └────────────┘
src    └────────┘ └──────────┘    └────┘└────────────┘└─┘
typ    └────────┘└──────────┘    └────┘└────────────┘└─┘
doc    └────────┘ └──────────┘    └────┘              └─┘
txt    └────────┘ └──────────┘    └────┘              └─┘
par    └────────┘ └──────────┘    └────┘              └─┘
pid              └─────────┘                       └┘
st   ────────────────────────┘└──┘└─────────────────────┘└┘
3710    cases forall_mem_cons.1 H₁ with H₁₁ H₁₂,
id           └─────────────┘   └┘
src    └────┘└─────────────┘└─┘  └───────────┘
typ    └────┘└─────────────┘└─┘└┘└───────────┘
doc    └────┘               └─┘  └───────────┘
txt    └────┘               └─┘  └───────────┘
par    └────┘               └─┘  └───────────┘
pid                        └─┘  └───────────┘
st   ────────────────────────────────────────┘└─
3711    cases pairwise_cons.1 H₂ with H₂₁ H₂₂,
id           └───────────┘   └┘
src    └────┘└───────────┘└─┘  └───────────┘
typ    └────┘└───────────┘└─┘└┘└───────────┘
doc    └────┘             └─┘  └───────────┘
txt    └────┘             └─┘  └───────────┘
par    └────┘             └─┘  └───────────┘
pid                      └─┘  └───────────┘
st   ──────────────────────────────────────┘└─
3712    rintro x (rfl | hx) y (rfl | hy),
src    └──────────────────────────────┘
typ    └──────────────────────────────┘
doc    └──────────────────────────────┘
txt    └──────────────────────────────┘
par    └──────────────────────────────┘
pid          └────────────────────────┘
st   ─────────────────────────────────┘└─
3713    exacts [H₁₁, H₂₁ _ hy, H (H₂₁ _ hx), IH H₁₂ H₂₂ _ hx _ hy]
id             └─┘  └─┘   └┘    └─┘   └┘   └┘ └─┘ └─┘   └┘   └┘
src    └──────┘   └┘   └─┘  └┘     └─┘  └─┘        └─┘  └─┘  └┘
typ    └──────┘└─┘└┘└─┘└─┘└┘└┘ └─┘└─┘└┘└─┘└┘└─┘└─┘└─┘└┘└─┘└┘└┘
doc    └──────┘   └┘   └─┘  └┘     └─┘  └─┘        └─┘  └─┘  └┘
txt    └──────┘   └┘   └─┘  └┘     └─┘  └─┘        └─┘  └─┘  └┘
par    └──────┘   └┘   └─┘  └┘     └─┘  └─┘        └─┘  └─┘  └┘
pid          └┘   └┘   └─┘  └┘     └─┘  └─┘        └─┘  └─┘  
st   ────────────────────────────────────────────────────────────┘
3714  end
st   └─┘
3715  
3716  lemma forall_of_pairwise (H : symmetric R) {l : list α}
id                                 └───────┘        └──┘ 
src                                └───────┘         └──┘
typ                                └───────┘        └──┘ 
3717     (hl : pairwise R l) : (∀a∈l, ∀b∈l, a ≠ b → R a b) :=
id            └──────┘                      
src           └──────┘                       
typ           └──────┘                      
doc           └──────┘
3718  forall_of_forall_of_pairwise
id   └──────────────────────────┘
src  └──────────────────────────┘
typ  └──────────────────────────┘
3719    (λ a b h hne, H (h hne.symm))
id           └─┘     └─┘└───┘
src                          └───┘
typ          └─┘     └─┘└───┘
3720    (λ _ _ h, (h rfl).elim)
id              └─┘ └──┘
src                 └─┘ └──┘
typ             └─┘ └──┘
3721    (pairwise.imp (λ _ _ h _, h) hl)
id      └──────────┘           └┘
src     └──────────┘
typ     └──────────┘           └┘
3722  
3723  theorem pairwise_singleton (R) (a : α) : pairwise R [a] :=
id                                           └──────┘  
src                                           └──────┘    
typ                                          └──────┘  
doc                                           └──────┘
3724  by simp only [pairwise_cons, mem_singleton, forall_prop_of_false (not_mem_nil _), forall_true_iff, pairwise.nil, and_true]
id                 └───────────┘  └───────────┘  └──────────────────┘  └─────────┘     └─────────────┘  └──────────┘  └──────┘
src     └─────────┘└───────────┘└┘└───────────┘└┘└──────────────────┘ └─────────┘└───┘└─────────────┘└┘└──────────┘└┘└──────┘└─
typ     └─────────┘└───────────┘└┘└───────────┘└┘└──────────────────┘ └─────────┘└───┘└─────────────┘└┘└──────────┘└┘└──────┘└─
doc     └─────────┘             └┘             └┘                                └───┘               └┘            └┘        └─
txt     └─────────┘             └┘             └┘                                └───┘               └┘            └┘        └─
par     └─────────┘             └┘             └┘                                └───┘               └┘            └┘        └─
pid         └──┘└┘             └┘             └┘                                └───┘               └┘            └┘        
st     └────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
3725  
src  
typ  
doc  
txt  
par  
pid  
st   
3726  theorem pairwise_pair {a b : α} : pairwise R [a, b] ↔ R a b :=
id                                    └──────┘       
src                                    └──────┘       
typ                                   └──────┘       
doc                                    └──────┘
3727  by simp only [pairwise_cons, mem_singleton, forall_eq, forall_prop_of_false (not_mem_nil _), forall_true_iff, pairwise.nil, and_true]
id                 └───────────┘  └───────────┘  └───────┘  └──────────────────┘  └─────────┘     └─────────────┘  └──────────┘  └──────┘
src     └─────────┘└───────────┘└┘└───────────┘└┘└───────┘└┘└──────────────────┘ └─────────┘└───┘└─────────────┘└┘└──────────┘└┘└──────┘└─
typ     └─────────┘└───────────┘└┘└───────────┘└┘└───────┘└┘└──────────────────┘ └─────────┘└───┘└─────────────┘└┘└──────────┘└┘└──────┘└─
doc     └─────────┘             └┘             └┘         └┘                                └───┘               └┘            └┘        └─
txt     └─────────┘             └┘             └┘         └┘                                └───┘               └┘            └┘        └─
par     └─────────┘             └┘             └┘         └┘                                └───┘               └┘            └┘        └─
pid         └──┘└┘             └┘             └┘         └┘                                └───┘               └┘            └┘        
st     └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
3728  
src  
typ  
doc  
txt  
par  
pid  
st   
3729  theorem pairwise_append {l₁ l₂ : list α} : pairwise R (l₁++l₂) ↔
id                                    └──┘     └──────┘   └┘└┘└┘  
src                                   └──┘      └──────┘      └┘    
typ                                   └──┘     └──────┘   └┘└┘└┘  
doc                                             └──────┘
3730    pairwise R l₁ ∧ pairwise R l₂ ∧ ∀ x ∈ l₁, ∀ y ∈ l₂, R x y :=
id     └──────┘  └┘  └──────┘  └┘       └┘       └┘    
src    └──────┘       └──────┘      
typ    └──────┘  └┘  └──────┘  └┘       └┘       └┘    
doc    └──────┘        └──────┘
3731  by induction l₁ with x l₁ IH; [simp only [list.pairwise.nil, forall_prop_of_false (not_mem_nil _), forall_true_iff, and_true, true_and, nil_append],
id                └┘                          └───────────────┘  └──────────────────┘  └─────────┘     └─────────────┘  └──────┘  └──────┘  └────────┘
src     └────────┘  └───────────┘  └─────────┘└───────────────┘└┘└──────────────────┘ └─────────┘└───┘└─────────────┘└┘└──────┘└┘└──────┘└┘└────────┘
typ     └────────┘└┘└───────────┘  └─────────┘└───────────────┘└┘└──────────────────┘ └─────────┘└───┘└─────────────┘└┘└──────┘└┘└──────┘└┘└────────┘
doc     └────────┘  └───────────┘   └─────────┘                 └┘                                └───┘               └┘        └┘        └┘          
txt     └────────┘  └───────────┘   └─────────┘                 └┘                                └───┘               └┘        └┘        └┘          
par     └────────┘  └───────────┘   └─────────┘                 └┘                                └───┘               └┘        └┘        └┘          
pid                └──────────┘       └──┘└┘                 └┘                                └───┘               └┘        └┘        └┘          
st     └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
3732  simp only [cons_append, pairwise_cons, forall_mem_append, IH, forall_mem_cons, forall_and_distrib, and_assoc, and.left_comm]]
id              └─────────┘  └───────────┘  └───────────────┘  └┘  └─────────────┘  └────────────────┘  └───────┘  └───────────┘
src  └─────────┘└─────────┘└┘└───────────┘└┘└───────────────┘└┘  └┘└─────────────┘└┘└────────────────┘└┘└───────┘└┘└───────────┘
typ  └─────────┘└─────────┘└┘└───────────┘└┘└───────────────┘└┘└┘└┘└─────────────┘└┘└────────────────┘└┘└───────┘└┘└───────────┘
doc  └─────────┘           └┘             └┘                 └┘  └┘               └┘                  └┘         └┘             
txt  └─────────┘           └┘             └┘                 └┘  └┘               └┘                  └┘         └┘             
par  └─────────┘           └┘             └┘                 └┘  └┘               └┘                  └┘         └┘             
pid      └──┘└┘           └┘             └┘                 └┘  └┘               └┘                  └┘         └┘             
st   ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
3733  
3734  theorem pairwise_append_comm (s : symmetric R) {l₁ l₂ : list α} :
id                                     └───────┘            └──┘ 
src                                    └───────┘             └──┘
typ                                    └───────┘            └──┘ 
3735    pairwise R (l₁++l₂) ↔ pairwise R (l₂++l₁) :=
id     └──────┘   └┘└┘└┘   └──────┘   └┘└┘└┘
src    └──────┘      └┘     └──────┘      └┘
typ    └──────┘   └┘└┘└┘   └──────┘   └┘└┘└┘
doc    └──────┘              └──────┘
3736  have ∀ l₁ l₂ : list α,
id                  └──┘ 
src                 └──┘
typ                 └──┘ 
3737    (∀ (x : α), x ∈ l₁ → ∀ (y : α), y ∈ l₂ → R x y) →
id                 └┘               └┘     
src                                     
typ                └┘               └┘     
3738    (∀ (x : α), x ∈ l₂ → ∀ (y : α), y ∈ l₁ → R x y),
id                  └┘               └┘     
src                                     
typ                 └┘               └┘     
3739  from λ l₁ l₂ a x xm y ym, s (a y ym x xm),
id          └┘ └┘   └┘  └┘      └┘  └┘
typ         └┘ └┘   └┘  └┘      └┘  └┘
3740  by simp only [pairwise_append, and.left_comm]; rw iff.intro (this l₁ l₂) (this l₂ l₁)
id                 └─────────────┘  └───────────┘      └───────┘               └──┘ └┘ └┘
src     └─────────┘└─────────────┘└┘└───────────┘  └─┘└───────┘         └┘         └─
typ     └─────────┘└─────────────┘└┘└───────────┘  └─┘└───────┘         └┘ └──┘└┘└┘└─
doc     └─────────┘               └┘               └─┘                  └┘         └─
txt     └─────────┘               └┘               └─┘                  └┘         └─
par     └─────────┘               └┘               └─┘                  └┘         └─
pid         └──┘└┘               └┘                                   └┘         
st     └──────────────────────────────────────────────┘└───────┘└──────────────────────────
3741  
src  
typ  
doc  
txt  
par  
pid  
st   
3742  theorem pairwise_middle (s : symmetric R) {a : α} {l₁ l₂ : list α} :
id                                └───────┘                   └──┘ 
src                               └───────┘                     └──┘
typ                               └───────┘                   └──┘ 
3743    pairwise R (l₁ ++ a::l₂) ↔ pairwise R (a::(l₁++l₂)) :=
id     └──────┘   └┘ └┘ └┘└┘   └──────┘   └┘ └┘└┘└┘
src    └──────┘       └┘  └┘     └──────┘     └┘   └┘
typ    └──────┘   └┘ └┘ └┘└┘   └──────┘   └┘ └┘└┘└┘
doc    └──────┘                   └──────┘
3744  show pairwise R (l₁ ++ ([a] ++ l₂)) ↔ pairwise R ([a] ++ l₁ ++ l₂),
id        └──────┘   └┘ └┘   └┘ └┘    └──────┘    └┘ └┘ └┘ └┘
src       └──────┘       └┘    └┘       └──────┘      └┘    └┘
typ       └──────┘   └┘ └┘   └┘ └┘    └──────┘    └┘ └┘ └┘ └┘
doc       └──────┘                         └──────┘
3745  by rw [← append_assoc, pairwise_append, @pairwise_append _ _ ([a] ++ l₁), pairwise_append_comm s];
id            └──────────┘  └─────────────┘   └─────────────┘       └┘ └┘   └──────────────────┘ 
src     └────┘└──────────┘└┘└─────────────┘└┘ └─────────────┘└───┘  └┘  └─┘└──────────────────┘ 
typ     └────┘└──────────┘└┘└─────────────┘└┘ └─────────────┘└───┘ └┘└┘└─┘└──────────────────┘
doc     └────┘            └┘               └┘                └───┘        └─┘                     
txt     └────┘            └┘               └┘                └───┘        └─┘                     
par     └────┘            └┘               └┘                └───┘        └─┘                     
pid       └──┘            └┘               └┘                └───┘        └─┘                     
st     └─────────────────┘└───────────────┘└────────────────────────────────┘└──────────────────────┘└─
3746     simp only [mem_append, or_comm]
id                 └────────┘  └─────┘
src     └─────────┘└────────┘└┘└─────┘└─
typ     └─────────┘└────────┘└┘└─────┘└─
doc     └─────────┘          └┘       └─
txt     └─────────┘          └┘       └─
par     └─────────┘          └┘       └─
pid         └──┘└┘          └┘       
st   ───────────────────────────────────
3747  
src  
typ  
doc  
txt  
par  
pid  
st   
3748  theorem pairwise_map (f : β → α) :
id                                
typ                               
3749    ∀ {l : list β}, pairwise R (map f l) ↔ pairwise (λ a b : β, R (f a) (f b)) l
id           └──┘    └──────┘   └─┘     └──────┘                      
src           └──┘     └──────┘    └─┘       └──────┘
typ          └──┘    └──────┘   └─┘     └──────┘                      
doc                    └──────┘               └──────┘
3750  | []     := by simp only [map, pairwise.nil]
id     └┘                      └─┘  └──────────┘
src    └┘           └─────────┘└─┘└┘└──────────┘└┘
typ    └┘           └─────────┘└─┘└┘└──────────┘└┘
doc                 └─────────┘   └┘            └┘
txt                 └─────────┘   └┘            └┘
par                 └─────────┘   └┘            └┘
pid                     └──┘└┘   └┘            
st                 └─────────────────────────────┘
3751  | (b::l) :=
id      └┘
src      └┘
typ     └┘
3752    have (∀ a b', b' ∈ l → f b' = a → R (f b) a) ↔ ∀ (b' : β), b' ∈ l → R (f b) (f b'), from
id              └┘  └┘       └┘                         └┘              └┘
src                                                               
typ             └┘  └┘       └┘                         └┘              └┘
3753    forall_swap.trans $ forall_congr $ λ a, forall_swap.trans $ by simp only [forall_eq'],
id     └─────────┘└────┘   └──────────┘       └─────────┘└────┘                 └────────┘
src    └─────────┘└────┘   └──────────┘        └─────────┘└────┘      └─────────┘└────────┘
typ    └─────────┘└────┘   └──────────┘       └─────────┘└────┘      └─────────┘└────────┘
doc                                                                   └─────────┘          
txt                                                                   └─────────┘          
par                                                                   └─────────┘          
pid                                                                       └──┘└┘          
st                                                                   └─────────────────────┘
3754    by simp only [map, pairwise_cons, mem_map, exists_imp_distrib, and_imp, this, pairwise_map]
id                   └─┘  └───────────┘  └─────┘  └────────────────┘  └─────┘  └──┘
src       └─────────┘└─┘└┘└───────────┘└┘└─────┘└┘└────────────────┘└┘└─────┘└┘    └┘            └─
typ       └─────────┘└─┘└┘└───────────┘└┘└─────┘└┘└────────────────┘└┘└─────┘└┘└──┘└┘└──────────┘└─
doc       └─────────┘   └┘             └┘       └┘                  └┘       └┘    └┘            └─
txt       └─────────┘   └┘             └┘       └┘                  └┘       └┘    └┘            └─
par       └─────────┘   └┘             └┘       └┘                  └┘       └┘    └┘            └─
pid           └──┘└┘   └┘             └┘       └┘                  └┘       └┘    └┘            
st       └─────────────────────────────────────────────────────────────────────────────────────────
3755  
src  
typ  
doc  
txt  
par  
pid  
st   
3756  theorem pairwise_of_pairwise_map {S : β → β → Prop} (f : α → β)
id                                                             
typ                                                            
3757    (H : ∀ a b : α, S (f a) (f b) → R a b) {l : list α}
id                                        └──┘ 
src                                                └──┘
typ                                       └──┘ 
3758    (p : pairwise S (map f l)) : pairwise R l :=
id          └──────┘   └─┘       └──────┘  
src         └──────┘    └─┘         └──────┘
typ         └──────┘   └─┘       └──────┘  
doc         └──────┘                └──────┘
3759  ((pairwise_map f).1 p).imp H
id     └──────────┘     └─┘  
src    └──────────┘       └─┘
typ    └──────────┘     └─┘  
3760  
3761  theorem pairwise_map_of_pairwise {S : β → β → Prop} (f : α → β)
id                                                             
typ                                                            
3762    (H : ∀ a b : α, R a b → S (f a) (f b)) {l : list α}
id                                        └──┘ 
src                                                └──┘
typ                                       └──┘ 
3763    (p : pairwise R l) : pairwise S (map f l) :=
id          └──────┘      └──────┘   └─┘  
src         └──────┘        └──────┘    └─┘
typ         └──────┘      └──────┘   └─┘  
doc         └──────┘        └──────┘
3764  (pairwise_map f).2 $ p.imp H
id    └──────────┘      └──┘ 
src   └──────────┘        └──┘
typ   └──────────┘      └──┘ 
3765  
3766  theorem pairwise_filter_map (f : β → option α) {l : list β} :
id                                       └────┘        └──┘ 
src                                       └────┘         └──┘
typ                                      └────┘        └──┘ 
3767    pairwise R (filter_map f l) ↔ pairwise (λ a a' : β, ∀ (b ∈ f a) (b' ∈ f a'), R b b') l :=
id     └──────┘   └────────┘     └──────┘                      └┘    └┘     └┘  
src    └──────┘    └────────┘       └──────┘
typ    └──────┘   └────────┘     └──────┘                      └┘    └┘     └┘  
doc    └──────┘                      └──────┘
3768  let S (a a' : β) := ∀ (b ∈ f a) (b' ∈ f a'), R b b' in
id                              └┘    └┘     └┘
typ                             └┘    └┘     └┘
3769  begin
st   └─────
3770    simp only [option.mem_def], induction l with a l IH,
id                └────────────┘             
src    └─────────┘└────────────┘  └────────┘ └──────────┘
typ    └─────────┘└────────────┘  └────────┘└──────────┘
doc    └─────────┘                └────────┘ └──────────┘
txt    └─────────┘                └────────┘ └──────────┘
par    └─────────┘                └────────┘ └──────────┘
pid        └──┘└┘                          └─────────┘
st   ───────────────────────────┘└───────────────────────┘└─
3771    { simp only [filter_map, pairwise.nil] },
id                  └────────┘  └──────────┘
src      └─────────┘└────────┘└┘└──────────┘└┘
typ      └─────────┘└────────┘└┘└──────────┘└┘
doc      └─────────┘          └┘            └┘
txt      └─────────┘          └┘            └┘
par      └─────────┘          └┘            └┘
pid          └──┘└┘          └┘            
st   ───┘└───────────────────────────────────┘└┘
3772    cases e : f a with b,
id                
src    └────┘ └─┘  └─────┘
typ    └────┘ └─┘└─────┘
doc    └────┘ └─┘  └─────┘
txt    └────┘ └─┘  └─────┘
par    └────┘ └─┘  └─────┘
pid          └─┘  └─────┘
st   ─────────────────────┘└─
3773    { rw [filter_map_cons_none _ _ e, IH, pairwise_cons],
id           └──────────────────┘       └┘  └───────────┘
src      └──┘└──────────────────┘└───┘ └┘  └┘└───────────┘
typ      └──┘└──────────────────┘└───┘└┘└┘└┘└───────────┘
doc      └──┘                    └───┘ └┘  └┘             
txt      └──┘                    └───┘ └┘  └┘             
par      └──┘                    └───┘ └┘  └┘             
pid        └┘                    └───┘ └┘  └┘             
st   ───┘└────────────────────────────┘└──┘└─────────────┘└─
3774      simp only [e, forall_prop_of_false not_false, forall_3_true_iff, true_and] },
id                    └──────────────────┘ └───────┘  └───────────────┘  └──────┘
src      └─────────┘ └┘└──────────────────┘└───────┘└┘└───────────────┘└┘└──────┘└┘
typ      └─────────┘└┘└──────────────────┘└───────┘└┘└───────────────┘└┘└──────┘└┘
doc      └─────────┘ └┘                             └┘                 └┘        └┘
txt      └─────────┘ └┘                             └┘                 └┘        └┘
par      └─────────┘ └┘                             └┘                 └┘        └┘
pid          └──┘└┘ └┘                             └┘                 └┘        
st   ──────────────────────────────────────────────────────────────────────────────┘└┘
3775    rw [filter_map_cons_some _ _ _ e],
id         └──────────────────┘       
src    └──┘└──────────────────┘└─────┘ 
typ    └──┘└──────────────────┘└─────┘
doc    └──┘                    └─────┘ 
txt    └──┘                    └─────┘ 
par    └──┘                    └─────┘ 
pid      └┘                    └─────┘ 
st   ─────────────────────────────────┘└─
3776    simp only [pairwise_cons, mem_filter_map, exists_imp_distrib, and_imp, IH, e, forall_eq'],
id                └───────────┘  └────────────┘  └────────────────┘  └─────┘  └┘    └────────┘
src    └─────────┘└───────────┘└┘└────────────┘└┘└────────────────┘└┘└─────┘└┘  └┘ └┘└────────┘
typ    └─────────┘└───────────┘└┘└────────────┘└┘└────────────────┘└┘└─────┘└┘└┘└┘└┘└────────┘
doc    └─────────┘             └┘              └┘                  └┘       └┘  └┘ └┘          
txt    └─────────┘             └┘              └┘                  └┘       └┘  └┘ └┘          
par    └─────────┘             └┘              └┘                  └┘       └┘  └┘ └┘          
pid        └──┘└┘             └┘              └┘                  └┘       └┘  └┘ └┘          
st   ──────────────────────────────────────────────────────────────────────────────────────────┘└─
3777    show (∀ (a' : α) (x : β), x ∈ l → f x = some a' → R b a') ∧ pairwise S l ↔
id                                          
src    └───┘  └─────┘ └─────┘                   └┘            
typ    └───┘  └─────┘ └─────┘                  └┘            
doc    └───┘  └─────┘ └─────┘                    └┘            
txt    └───┘  └─────┘ └─────┘                    └┘            
par    └───┘  └─────┘ └─────┘                    └┘            
pid    └───┘  └─────┘ └─────┘                    └┘            
st   ─────────────────────────────────────────────────────────────────────────────
3778          (∀ (a' : β), a' ∈ l → ∀ (b' : α), f a' = some b' → R b b') ∧ pairwise S l,
id                                                └──┘              └──────┘  
src  ───────┘  └─────┘        └─────┘      └──┘       └┘ └──────┘ 
typ  ───────┘  └─────┘       └─────┘   └──┘     └┘ └──────┘
doc  ───────┘  └─────┘        └─────┘                 └┘ └──────┘ 
txt  ───────┘  └─────┘        └─────┘                 └┘          
par  ───────┘  └─────┘        └─────┘                 └┘          
pid  ───────┘  └─────┘        └─────┘                 └┘          
st   ────────────────────────────────────────────────────────────────────────────────┘└─
3779    from and_congr ⟨λ h b mb a ma, h a b mb ma, λ h a b mb ma, h b mb a ma⟩ iff.rfl
id          └───────┘                                                          └─────┘
src    └───┘└───────┘  └────────────┘       └┘ └────────────┘       └┘└─────┘
typ    └───┘└───────┘  └────────────┘       └┘ └────────────┘       └┘└─────┘
doc    └───┘           └────────────┘       └┘ └────────────┘       └┘       
txt    └───┘           └────────────┘       └┘ └────────────┘       └┘       
par    └───┘           └────────────┘       └┘ └────────────┘       └┘       
pid    └───┘           └────────────┘       └┘ └────────────┘       └┘       
st   ─────────────────────────────────────────────────────────────────────────────────┘
3780  end
st   └─┘
3781  
3782  theorem pairwise_filter_map_of_pairwise {S : β → β → Prop} (f : α → option β)
id                                                                    └────┘ 
src                                                                      └────┘
typ                                                                   └────┘ 
3783    (H : ∀ (a a' : α), R a a' → ∀ (b ∈ f a) (b' ∈ f a'), S b b') {l : list α}
id                         └┘            └┘    └┘     └┘       └──┘ 
src                                                                      └──┘
typ                        └┘            └┘    └┘     └┘       └──┘ 
3784    (p : pairwise R l) : pairwise S (filter_map f l) :=
id          └──────┘      └──────┘   └────────┘  
src         └──────┘        └──────┘    └────────┘
typ         └──────┘      └──────┘   └────────┘  
doc         └──────┘        └──────┘
3785  (pairwise_filter_map _).2 $ p.imp H
id    └─────────────────┘       └──┘ 
src   └─────────────────┘        └──┘
typ   └─────────────────┘       └──┘ 
3786  
3787  theorem pairwise_filter (p : α → Prop) [decidable_pred p] {l : list α} :
id                                          └────────────┘        └──┘ 
src                                          └────────────┘         └──┘
typ                                         └────────────┘        └──┘ 
3788    pairwise R (filter p l) ↔ pairwise (λ x y, p x → p y → R x y) l :=
id     └──────┘   └────┘     └──────┘                   
src    └──────┘    └────┘       └──────┘
typ    └──────┘   └────┘     └──────┘                   
doc    └──────┘                  └──────┘
3789  begin
st   └─────
3790    rw [← filter_map_eq_filter, pairwise_filter_map],
id           └──────────────────┘  └─────────────────┘
src    └────┘└──────────────────┘└┘└─────────────────┘
typ    └────┘└──────────────────┘└┘└─────────────────┘
doc    └────┘                    └┘                   
txt    └────┘                    └┘                   
par    └────┘                    └┘                   
pid      └──┘                    └┘                   
st   ───────────────────────────┘└───────────────────┘└──
3791    apply pairwise.iff, intros, simp only [option.mem_def, option.guard_eq_some, and_imp, forall_eq'],
id           └──────────┘                     └────────────┘  └──────────────────┘  └─────┘  └────────┘
src    └────┘└──────────┘  └────┘  └─────────┘└────────────┘└┘└──────────────────┘└┘└─────┘└┘└────────┘
typ    └────┘└──────────┘  └────┘  └─────────┘└────────────┘└┘└──────────────────┘└┘└─────┘└┘└────────┘
doc    └────┘              └────┘  └─────────┘              └┘                    └┘       └┘          
txt    └────┘              └────┘  └─────────┘              └┘                    └┘       └┘          
par    └────┘              └────┘  └─────────┘              └┘                    └┘       └┘          
pid                                   └──┘└┘              └┘                    └┘       └┘          
st   ───────────────────┘└──────┘└─────────────────────────────────────────────────────────────────────┘└─
3792  end
st   ──┘
3793  
3794  theorem pairwise_filter_of_pairwise (p : α → Prop) [decidable_pred p] {l : list α}
id                                                      └────────────┘        └──┘ 
src                                                      └────────────┘         └──┘
typ                                                     └────────────┘        └──┘ 
3795    : pairwise R l → pairwise R (filter p l) :=
id       └──────┘     └──────┘   └────┘  
src      └──────┘       └──────┘    └────┘
typ      └──────┘     └──────┘   └────┘  
doc      └──────┘       └──────┘
3796  pairwise_of_sublist (filter_sublist _)
id   └─────────────────┘  └────────────┘
src  └─────────────────┘  └────────────┘
typ  └─────────────────┘  └────────────┘
3797  
3798  theorem pairwise_join {L : list (list α)} : pairwise R (join L) ↔
id                              └──┘  └──┘      └──────┘   └──┘   
src                             └──┘  └──┘       └──────┘    └──┘    
typ                             └──┘  └──┘      └──────┘   └──┘   
doc                                              └──────┘
3799    (∀ l ∈ L, pairwise R l) ∧ pairwise (λ l₁ l₂, ∀ (x ∈ l₁) (y ∈ l₂), R x y) L :=
id             └──────┘     └──────┘    └┘ └┘       └┘      └┘       
src              └──────┘       └──────┘
typ            └──────┘     └──────┘    └┘ └┘       └┘      └┘       
doc              └──────┘        └──────┘
3800  begin
st   └─────
3801    induction L with l L IH, {simp only [join, pairwise.nil, forall_prop_of_false (not_mem_nil _), forall_const, and_self]},
id                                         └──┘  └──────────┘  └──────────────────┘  └─────────┘     └──────────┘  └──────┘
src    └────────┘ └──────────┘   └─────────┘└──┘└┘└──────────┘└┘└──────────────────┘ └─────────┘└───┘└──────────┘└┘└──────┘
typ    └────────┘└──────────┘   └─────────┘└──┘└┘└──────────┘└┘└──────────────────┘ └─────────┘└───┘└──────────┘└┘└──────┘
doc    └────────┘ └──────────┘   └─────────┘    └┘            └┘                                └───┘            └┘        
txt    └────────┘ └──────────┘   └─────────┘    └┘            └┘                                └───┘            └┘        
par    └────────┘ └──────────┘   └─────────┘    └┘            └┘                                └───┘            └┘        
pid              └─────────┘       └──┘└┘    └┘            └┘                                └───┘            └┘        
st   ────────────────────────┘└─────────────────────────────────────────────────────────────────────────────────────────────┘└┘
3802    have : (∀ (x : α), x ∈ l → ∀ (y : α) (x_1 : list α), x_1 ∈ L → y ∈ x_1 → R x y) ↔
id                                                └──┘                
src    └─────┘  └────┘      └────┘ └───────┘                     └┘ 
typ    └─────┘  └────┘      └────┘ └───────┘└──┘               └┘ 
doc    └─────┘  └────┘       └────┘ └───────┘                     └┘ 
txt    └─────┘  └────┘       └────┘ └───────┘                     └┘ 
par    └─────┘  └────┘       └────┘ └───────┘                     └┘ 
pid    └───┘└┘  └────┘       └────┘ └───────┘                     └┘ 
st   ────────────────────────────────────────────────────────────────────────────────────
3803            ∀ (a' : list α), a' ∈ L → ∀ (x : α), x ∈ l → ∀ (y : α), y ∈ a' → R x y :=
id                     └──┘                                                 
src  ─────────┘ └─────┘└──┘        └────┘       └────┘          └───
typ  ─────────┘ └─────┘└──┘       └────┘      └────┘       └───
doc  ─────────┘ └─────┘            └────┘       └────┘          └───
txt  ─────────┘ └─────┘            └────┘       └────┘          └───
par  ─────────┘ └─────┘            └────┘       └────┘          └───
pid  ─────────┘ └─────┘            └────┘       └────┘          └───
st   ────────────────────────────────────────────────────────────────────────────────────
3804      ⟨λ h a b c d e, h c d e a b, λ h c d e a b, h a b c d e⟩,
src  ───┘  └────────────┘      └┘ └────────────┘      
typ  ───┘  └────────────┘      └┘ └────────────┘      
doc  ───┘  └────────────┘      └┘ └────────────┘      
txt  ───┘  └────────────┘      └┘ └────────────┘      
par  ───┘  └────────────┘      └┘ └────────────┘      
pid  ───┘  └────────────┘      └┘ └────────────┘      
st   ───────────────────────────────────────────────────────────┘└─
3805    simp only [join, pairwise_append, IH, mem_join, exists_imp_distrib, and_imp, this, forall_mem_cons, pairwise_cons],
id                └──┘  └─────────────┘  └┘  └──────┘  └────────────────┘  └─────┘  └──┘  └─────────────┘  └───────────┘
src    └─────────┘└──┘└┘└─────────────┘└┘  └┘└──────┘└┘└────────────────┘└┘└─────┘└┘    └┘└─────────────┘└┘└───────────┘
typ    └─────────┘└──┘└┘└─────────────┘└┘└┘└┘└──────┘└┘└────────────────┘└┘└─────┘└┘└──┘└┘└─────────────┘└┘└───────────┘
doc    └─────────┘    └┘               └┘  └┘        └┘                  └┘       └┘    └┘               └┘             
txt    └─────────┘    └┘               └┘  └┘        └┘                  └┘       └┘    └┘               └┘             
par    └─────────┘    └┘               └┘  └┘        └┘                  └┘       └┘    └┘               └┘             
pid        └──┘└┘    └┘               └┘  └┘        └┘                  └┘       └┘    └┘               └┘             
st   ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘└─
3806    simp only [and_assoc, and_comm, and.left_comm],
id                └───────┘  └──────┘  └───────────┘
src    └─────────┘└───────┘└┘└──────┘└┘└───────────┘
typ    └─────────┘└───────┘└┘└──────┘└┘└───────────┘
doc    └─────────┘         └┘        └┘             
txt    └─────────┘         └┘        └┘             
par    └─────────┘         └┘        └┘             
pid        └──┘└┘         └┘        └┘             
st   ───────────────────────────────────────────────┘└─
3807  end
st   ──┘
3808  
3809  @[simp] theorem pairwise_reverse : ∀ {R} {l : list α},
id                                                └──┘ 
src                                                └──┘
typ                                               └──┘ 
doc    └──┘
3810    pairwise R (reverse l) ↔ pairwise (λ x y, R y x) l :=
id     └──────┘   └─────┘    └──────┘           
src    └──────┘    └─────┘     └──────┘
typ    └──────┘   └─────┘    └──────┘           
doc    └──────┘                 └──────┘
3811  suffices ∀ {R l}, @pairwise α R l → pairwise (λ x y, R y x) (reverse l),
id                    └──────┘      └──────┘            └─────┘ 
src                     └──────┘         └──────┘                 └─────┘
typ                   └──────┘      └──────┘            └─────┘ 
doc                     └──────┘         └──────┘
3812  from λ R l, ⟨λ p, reverse_reverse l ▸ this p, this⟩,
id                  └─────────────┘   └──┘   └──┘
src                    └─────────────┘   
typ                 └─────────────┘   └──┘   └──┘
3813  λ R l p, by induction p with a l h p IH;
id                      
src              └────────┘ └──────────────┘
typ           └────────┘└──────────────┘
doc              └────────┘ └──────────────┘
txt              └────────┘ └──────────────┘
par              └────────┘ └──────────────┘
pid                        └─────────────┘
st              └─────────────────────────────
3814    [apply pairwise.nil, simpa only [reverse_cons, pairwise_append, IH,
id           └──────────┘              └──────────┘  └─────────────┘  └┘
src    └────┘└──────────┘  └──────────┘└──────────┘└┘└─────────────┘└┘  └─
typ    └────┘└──────────┘  └──────────┘└──────────┘└┘└─────────────┘└┘└┘└─
doc     └────┘              └──────────┘            └┘               └┘  └─
txt     └────┘              └──────────┘            └┘               └┘  └─
par     └────┘              └──────────┘            └┘               └┘  └─
pid                             └──┘└┘            └┘               └┘  └─
st   ──────────────────────────────────────────────────────────────────────
3815      pairwise_cons, forall_prop_of_false (not_mem_nil _), forall_true_iff,
id       └───────────┘  └──────────────────┘  └─────────┘     └─────────────┘
src  ───┘└───────────┘└┘└──────────────────┘ └─────────┘└───┘└─────────────┘└─
typ  ───┘└───────────┘└┘└──────────────────┘ └─────────┘└───┘└─────────────┘└─
doc  ───┘             └┘                                └───┘               └─
txt  ───┘             └┘                                └───┘               └─
par  ───┘             └┘                                └───┘               └─
pid  ───┘             └┘                                └───┘               └─
st   ──────────────────────────────────────────────────────────────────────────
3816      pairwise.nil, mem_reverse, mem_singleton, forall_eq, true_and] using h]
id       └──────────┘  └─────────┘  └───────────┘  └───────┘  └──────┘        
src  ───┘└──────────┘└┘└─────────┘└┘└───────────┘└┘└───────┘└┘└──────┘└──────┘
typ  ───┘└──────────┘└┘└─────────┘└┘└───────────┘└┘└───────┘└┘└──────┘└──────┘
doc  ───┘            └┘           └┘             └┘         └┘        └──────┘
txt  ───┘            └┘           └┘             └┘         └┘        └──────┘
par  ───┘            └┘           └┘             └┘         └┘        └──────┘
pid  ───┘            └┘           └┘             └┘         └┘        └────┘
st   ──────────────────────────────────────────────────────────────────────────┘
3817  
3818  theorem pairwise_iff_nth_le {R} : ∀ {l : list α},
id                                           └──┘ 
src                                           └──┘
typ                                          └──┘ 
3819    pairwise R l ↔ ∀ i j (h₁ : j < length l) (h₂ : i < j), R (nth_le l i (lt_trans h₂ h₁)) (nth_le l j h₁)
id     └──────┘                └────┘                └────┘    └──────┘ └┘ └┘    └────┘   └┘
src    └──────┘                     └────┘                    └────┘      └──────┘          └────┘
typ    └──────┘                └────┘                └────┘    └──────┘ └┘ └┘    └────┘   └┘
doc    └──────┘
3820  | [] := by simp only [pairwise.nil, true_iff]; exact λ i j h, (not_lt_zero j).elim h
id     └┘                  └──────────┘  └──────┘                   └─────────┘
src    └┘       └─────────┘└──────────┘└┘└──────┘  └────┘ └──────┘ └─────────┘ └─────┘ 
typ    └┘       └─────────┘└──────────┘└┘└──────┘  └────┘ └──────┘ └─────────┘ └─────┘ 
doc             └─────────┘            └┘          └────┘ └──────┘             └─────┘ 
txt             └─────────┘            └┘          └────┘ └──────┘             └─────┘ 
par             └─────────┘            └┘          └────┘ └──────┘             └─────┘ 
pid                 └──┘└┘            └┘                └──────┘             └─────┘ 
st             └─────────────────────────────────────────────────────────────────────────┘
3821  | (a::l) := begin
id       └┘
src      └┘
typ      └┘
st               └─────
3822    rw [pairwise_cons, pairwise_iff_nth_le],
id         └───────────┘
src    └──┘└───────────┘└┘                   
typ    └──┘└───────────┘└┘└─────────────────┘
doc    └──┘             └┘                   
txt    └──┘             └┘                   
par    └──┘             └┘                   
pid      └┘             └┘                   
st   ──────────────────┘└───────────────────┘└──
3823    refine ⟨λ H i j h₁ h₂, _, λ H, ⟨λ a' m, _,
src    └─────┘  └───────────────┘ └──┘  └─────────
typ    └─────┘  └───────────────┘ └──┘  └─────────
doc    └─────┘  └───────────────┘ └──┘  └─────────
txt    └─────┘  └───────────────┘ └──┘  └─────────
par    └─────┘  └───────────────┘ └──┘  └─────────
pid            └───────────────┘ └──┘  └─────────
st   ─────────────────────────────────────────────
3824      λ i j h₁ h₂, H _ _ (succ_lt_succ h₁) (succ_lt_succ h₂)⟩⟩,
id                                             └──────────┘
src  ───┘ └──────────┘ └───┘               └┘ └──────────┘  └─┘
typ  ───┘ └──────────┘ └───┘               └┘ └──────────┘  └─┘
doc  ───┘ └──────────┘ └───┘               └┘               └─┘
txt  ───┘ └──────────┘ └───┘               └┘               └─┘
par  ───┘ └──────────┘ └───┘               └┘               └─┘
pid  ───┘ └──────────┘ └───┘               └┘               └─┘
st   ───────────────────────────────────────────────────────────┘└─
3825    { cases j with j, {exact (not_lt_zero _).elim h₂},
id                              └─────────┘         └┘
src      └────┘ └─────┘   └────┘ └─────────┘└───────┘
typ      └────┘└─────┘   └────┘ └─────────┘└───────┘└┘
doc      └────┘ └─────┘   └────┘            └───────┘
txt      └────┘ └─────┘   └────┘            └───────┘
par      └────┘ └─────┘   └────┘            └───────┘
pid            └─────┘                    └───────┘
st   ───┘└────────────┘└──────────────────────────────┘└┘
3826      cases i with i,
id             
src      └────┘ └─────┘
typ      └────┘└─────┘
doc      └────┘ └─────┘
txt      └────┘ └─────┘
par      └────┘ └─────┘
pid            └─────┘
st   ─────────────────┘└─
3827      { exact H.1 _ (nth_le_mem l _ _) },
id                     └────────┘ 
src        └────┘ └───┘ └────────┘ └────┘
typ        └────┘└───┘ └────────┘└────┘
doc        └────┘ └───┘            └────┘
txt        └────┘ └───┘            └────┘
par        └────┘ └───┘            └────┘
pid              └───┘            └───┘
st   ─────┘└─────────────────────────────┘└┘
3828      { exact H.2 _ _ (lt_of_succ_lt_succ h₁) (lt_of_succ_lt_succ h₂) } },
id                                          └┘   └────────────────┘ └┘
src        └────┘ └─────┘                     └┘ └────────────────┘  └┘
typ        └────┘└─────┘                   └┘└┘ └────────────────┘└┘└┘
doc        └────┘ └─────┘                     └┘                     └┘
txt        └────┘ └─────┘                     └┘                     └┘
par        └────┘ └─────┘                     └┘                     └┘
pid              └─────┘                     └┘                     
st   ───────────────────────────────────────────────────────────────────┘└──┘
3829    { rcases nth_le_of_mem m with ⟨n, h, rfl⟩,
id              └───────────┘ 
src      └─────┘└───────────┘ └───────────────┘
typ      └─────┘└───────────┘└───────────────┘
doc      └─────┘              └───────────────┘
txt      └─────┘              └───────────────┘
par      └─────┘              └───────────────┘
pid                          └───────────────┘
st   ──────────────────────────────────────────┘└─
3830      exact H _ _ (succ_lt_succ h) (succ_pos _) }
id                   └──────────┘    └──────┘
src      └────┘ └───┘ └──────────┘ └┘ └──────┘└──┘
typ      └────┘└───┘ └──────────┘└┘ └──────┘└──┘
doc      └────┘ └───┘              └┘         └──┘
txt      └────┘ └───┘              └┘         └──┘
par      └────┘ └───┘              └┘         └──┘
pid            └───┘              └┘         └─┘
st   ─────────────────────────────────────────────┘└─
3831  end
st   ──┘
3832  
3833  theorem pairwise_sublists' {R} : ∀ {l : list α}, pairwise R l →
id                                          └──┘    └──────┘  
src                                          └──┘     └──────┘
typ                                         └──┘    └──────┘  
doc                                                   └──────┘
3834    pairwise (lex (swap R)) (sublists' l)
id     └──────┘  └─┘  └──┘     └───────┘ 
src    └──────┘  └─┘  └──┘      └───────┘
typ    └──────┘  └─┘  └──┘     └───────┘ 
doc    └──────┘                 └───────┘
3835  | _ pairwise.nil := pairwise_singleton _ _
id       └──────────┘    └────────────────┘
src      └──────────┘    └────────────────┘
typ      └──────────┘    └────────────────┘
3836  | _ (@pairwise.cons _ _ a l H₁ H₂) :=
id         └───────────┘
src        └───────────┘
typ        └───────────┘
3837    begin
st     └─────
3838      simp only [sublists'_cons, pairwise_append, pairwise_map, mem_sublists', mem_map, exists_imp_distrib, and_imp],
id                  └────────────┘  └─────────────┘  └──────────┘  └───────────┘  └─────┘  └────────────────┘  └─────┘
src      └─────────┘└────────────┘└┘└─────────────┘└┘└──────────┘└┘└───────────┘└┘└─────┘└┘└────────────────┘└┘└─────┘
typ      └─────────┘└────────────┘└┘└─────────────┘└┘└──────────┘└┘└───────────┘└┘└─────┘└┘└────────────────┘└┘└─────┘
doc      └─────────┘              └┘               └┘            └┘             └┘       └┘                  └┘       
txt      └─────────┘              └┘               └┘            └┘             └┘       └┘                  └┘       
par      └─────────┘              └┘               └┘            └┘             └┘       └┘                  └┘       
pid          └──┘└┘              └┘               └┘            └┘             └┘       └┘                  └┘       
st   ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘└─
3839      have IH := pairwise_sublists' H₂,
id                  └────────────────┘ └┘
src      └─────────┘                  
typ      └─────────┘└────────────────┘└┘
doc      └─────────┘                  
txt      └─────────┘                  
par      └─────────┘                  
pid      └─────┘└─┘                  
st   ───────────────────────────────────┘└─
3840      refine ⟨IH, IH.imp (λ l₁ l₂, lex.cons), _⟩,
id                   └────┘           └──────┘
src      └─────┘   └┘└────┘  └──────┘└──────┘└───┘
typ      └─────┘   └┘└────┘  └──────┘└──────┘└───┘
doc      └─────┘   └┘        └──────┘        └───┘
txt      └─────┘   └┘        └──────┘        └───┘
par      └─────┘   └┘        └──────┘        └───┘
pid               └┘        └──────┘        └───┘
st   ─────────────────────────────────────────────┘└─
3841      intros l₁ sl₁ x l₂ sl₂ e, subst e,
id                                       
src      └──────────────────────┘  └────┘
typ      └──────────────────────┘  └────┘
doc      └──────────────────────┘  └────┘
txt      └──────────────────────┘  └────┘
par      └──────────────────────┘  └────┘
pid            └────────────────┘       
st   ───────────────────────────┘└───────┘└─
3842      cases l₁ with b l₁, {constructor},
id             └┘
src      └────┘  └────────┘   └─────────┘
typ      └────┘└┘└────────┘   └─────────┘
doc      └────┘  └────────┘   └─────────┘
txt      └────┘  └────────┘   └─────────┘
par      └────┘  └────────┘   └─────────┘
pid             └────────┘
st   ─────────────────────┘└────────────┘└┘
3843      exact lex.rel (H₁ _ $ subset_of_sublist sl₁ $ mem_cons_self _ _)
id             └─────┘  └┘     └───────────────┘ └─┘   └───────────┘
src      └────┘└─────┘   └─┘ └───────────────┘    └───────────┘└─────
typ      └────┘└─────┘ └┘└─┘ └───────────────┘└─┘ └───────────┘└─────
doc      └────┘          └─┘                                   └─────
txt      └────┘          └─┘                                   └─────
par      └────┘          └─┘                                   └─────
pid                     └─┘                                   └───┘
st   ─────────────────────────────────────────────────────────────────────
3844    end
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
3845  
3846  theorem pairwise_sublists {R} {l : list α} (H : pairwise R l) :
id                                      └──┘        └──────┘  
src                                     └──┘         └──────┘
typ                                     └──┘        └──────┘  
doc                                                  └──────┘
3847    pairwise (λ l₁ l₂, lex R (reverse l₁) (reverse l₂)) (sublists l) :=
id     └──────┘    └┘ └┘  └─┘   └─────┘ └┘   └─────┘ └┘    └──────┘ 
src    └──────┘           └─┘    └─────┘      └─────┘       └──────┘
typ    └──────┘    └┘ └┘  └─┘   └─────┘ └┘   └─────┘ └┘    └──────┘ 
doc    └──────┘                                             └──────┘
3848  by have := pairwise_sublists' (pairwise_reverse.2 H);
id              └────────────────┘  └──────────────┘   
src     └──────┘└────────────────┘ └──────────────┘└─┘ 
typ     └──────┘└────────────────┘ └──────────────┘└─┘
doc     └──────┘                                   └─┘ 
txt     └──────┘                                   └─┘ 
par     └──────┘                                   └─┘ 
pid     └───┘└─┘                                   └─┘ 
st     └───────────────────────────────────────────────────
3849     rwa [sublists'_reverse, pairwise_map] at this
id           └───────────────┘  └──────────┘
src     └───┘└───────────────┘└┘└──────────┘└─────────
typ     └───┘└───────────────┘└┘└──────────┘└─────────
doc     └───┘                 └┘            └─────────
txt     └───┘                 └┘            └─────────
par     └───┘                 └┘            └─────────
pid        └┘                 └┘            └──────┘
st   ───────┘└───────────────┘└────────────┘└────────
3850  
src  
typ  
doc  
txt  
par  
pid  
st   
3851  /- pairwise reduct -/
src  ──────────────────────
typ  ──────────────────────
doc  ──────────────────────
txt  ──────────────────────
par  ──────────────────────
pid  ──────────────────────
st   ──────────────────────
3852  
src  
typ  
doc  
txt  
par  
pid  
st   
3853  variable [decidable_rel R]
id             └───────────┘
src            └───────────┘
typ            └───────────┘
3854  
3855  @[simp] theorem pw_filter_nil : pw_filter R [] = [] := rfl
id                                   └───────┘  └┘  └┘    └─┘
src                                  └───────┘   └┘  └┘    └─┘
typ                                  └───────┘  └┘  └┘    └─┘
doc    └──┘                          └───────┘
3856  
3857  @[simp] theorem pw_filter_cons_of_pos {a : α} {l : list α} (h : ∀ b ∈ pw_filter R l, R a b) :
id                                                     └──┘             └───────┘      
src                                                     └──┘               └───────┘
typ                                                    └──┘             └───────┘      
doc    └──┘                                                                └───────┘
3858    pw_filter R (a::l) = a :: pw_filter R l := if_pos h
id     └───────┘   └┘    └┘ └───────┘      └────┘ 
src    └───────┘     └┘      └┘ └───────┘        └────┘
typ    └───────┘   └┘    └┘ └───────┘      └────┘ 
doc    └───────┘                 └───────┘
3859  
3860  @[simp] theorem pw_filter_cons_of_neg {a : α} {l : list α} (h : ¬ ∀ b ∈ pw_filter R l, R a b) :
id                                                     └──┘              └───────┘      
src                                                     └──┘                └───────┘
typ                                                    └──┘              └───────┘      
doc    └──┘                                                                  └───────┘
3861    pw_filter R (a::l) = pw_filter R l := if_neg h
id     └───────┘   └┘   └───────┘      └────┘ 
src    └───────┘     └┘    └───────┘        └────┘
typ    └───────┘   └┘   └───────┘      └────┘ 
doc    └───────┘            └───────┘
3862  
3863  theorem pw_filter_map (f : β → α) : Π (l : list β), pw_filter R (map f l) = map f (pw_filter (λ x y, R (f x) (f y)) l)
id                                           └──┘    └───────┘   └─┘     └─┘   └───────┘                 
src                                             └──┘     └───────┘    └─┘       └─┘    └───────┘
typ                                          └──┘    └───────┘   └─┘     └─┘   └───────┘                 
doc                                                      └───────┘                      └───────┘
3864  | [] := rfl
id     └┘    └─┘
src    └┘    └─┘
typ    └┘    └─┘
3865  | (x :: xs) :=
id       └┘ └┘
src       └┘
typ      └┘ └┘
3866    if h : ∀ b ∈ pw_filter R (map f xs), R (f x) b
id     └┘          └───────┘   └─┘             
src    └┘           └───────┘    └─┘
typ    └┘          └───────┘   └─┘             
doc                 └───────┘
3867      then have h' : ∀ (b : β), b ∈ pw_filter (λ (x y : β), R (f x) (f y)) xs → R (f x) (f b),
id                                  └───────┘                                     
src                                   └───────┘
typ                                 └───────┘                                     
doc                                    └───────┘
3868             from λ b hb, h _ (by rw [pw_filter_map]; apply mem_map_of_mem _ hb),
id                      └┘             └───────────┘         └────────────┘   └┘
src                                  └──┘               └────┘└────────────┘└─┘
typ                     └┘         └──┘└───────────┘  └────┘└────────────┘└─┘└┘
doc                                  └──┘               └────┘              └─┘
txt                                  └──┘               └────┘              └─┘
par                                  └──┘               └────┘              └─┘
pid                                    └┘                                  └─┘
st                                  └────────────────┘└─────────────────────────┘
3869           by rw [map,pw_filter_cons_of_pos h,pw_filter_cons_of_pos h',pw_filter_map,map]
id                   └─┘ └───────────────────┘  └───────────────────┘ └┘ └───────────┘ └─┘
src              └──┘└─┘└───────────────────┘ └───────────────────┘               └─┘└─
typ              └──┘└─┘└───────────────────┘└───────────────────┘└┘└───────────┘└─┘└─
doc              └──┘                                                                └─
txt              └──┘                                                                └─
par              └──┘                                                                └─
pid                └┘                                                                
st              └──────┘└──────────────────────┘└───────────────────────┘└────────────┘└──┘
3870      else have h' : ¬∀ (b : β), b ∈ pw_filter (λ (x y : β), R (f x) (f y)) xs → R (f x) (f b),
id            └──┘                  └───────┘                                     
src  ───┘                             └───────┘
typ  ───┘     └──┘                  └───────┘                                     
doc  ───┘                               └───────┘
txt  ───┘
par  ───┘
pid  ───┘
st   ───┘
3871             from λ hh, h $ λ a ha,
id                     └┘        └┘
typ                    └┘        └┘
3872             by { rw [pw_filter_map,mem_map] at ha, rcases ha with ⟨b,hb₀,hb₁⟩,
id                       └───────────┘ └─────┘                └┘
src                  └──┘             └─────┘└─────┘  └─────┘  └───────────────┘
typ                  └──┘└───────────┘└─────┘└─────┘  └─────┘└┘└───────────────┘
doc                  └──┘                    └─────┘  └─────┘  └───────────────┘
txt                  └──┘                    └─────┘  └─────┘  └───────────────┘
par                  └──┘                    └─────┘  └─────┘  └───────────────┘
pid                    └┘                    └────┘          └───────────────┘
st                └──────────────────┘└──────┘└────┘└──────────────────────────┘└─
3873                  subst a, exact hh _ hb₀, },
id                                 └┘   └─┘
src                  └────┘   └────┘  └─┘
typ                  └────┘  └────┘└┘└─┘└─┘
doc                  └────┘   └────┘  └─┘
txt                  └────┘   └────┘  └─┘
par                  └────┘   └────┘  └─┘
pid                                 └─┘
st   ──────────────────────┘└──────────────┘└──┘
3874           by rw [map,pw_filter_cons_of_neg h,pw_filter_cons_of_neg h',pw_filter_map]
id                   └─┘ └───────────────────┘  └───────────────────┘ └┘ └───────────┘
src              └──┘└─┘└───────────────────┘ └───────────────────┘               └─
typ              └──┘└─┘└───────────────────┘└───────────────────┘└┘└───────────┘└─
doc              └──┘                                                             └─
txt              └──┘                                                             └─
par              └──┘                                                             └─
pid                └┘                                                             
st              └──────┘└──────────────────────┘└───────────────────────┘└────────────┘
3875  
src  
typ  
doc  
txt  
par  
pid  
st   
3876  theorem pw_filter_sublist : ∀ (l : list α), pw_filter R l <+ l
id                                     └──┘    └───────┘   └┘ 
src                                     └──┘     └───────┘     └┘
typ                                    └──┘    └───────┘   └┘ 
doc                                              └───────┘
3877  | []     := nil_sublist _
id     └┘        └─────────┘
src    └┘        └─────────┘
typ    └┘        └─────────┘
3878  | (x::l) := begin
id       └┘
src      └┘
typ      └┘
st               └─────
3879    by_cases (∀ y ∈ pw_filter R l, R x y),
id                     └───────┘      
src    └───────┘  └───┘└───────┘      
typ    └───────┘  └───┘└───────┘   
doc    └───────┘  └───┘└───────┘      
txt    └───────┘  └───┘               
par    └───────┘  └───┘               
pid              └───┘               
st   ──────────────────────────────────────┘└─
3880    { rw [pw_filter_cons_of_pos h],
id           └───────────────────┘ 
src      └──┘└───────────────────┘ 
typ      └──┘└───────────────────┘
doc      └──┘                      
txt      └──┘                      
par      └──┘                      
pid        └┘                      
st   ───┘└─────────────────────────┘└──
3881      exact cons_sublist_cons _ (pw_filter_sublist l) },
id             └───────────────┘    └───────────────┘ 
src      └────┘└───────────────┘└─┘                   └┘
typ      └────┘└───────────────┘└─┘ └───────────────┘└┘
doc      └────┘                 └─┘                   └┘
txt      └────┘                 └─┘                   └┘
par      └────┘                 └─┘                   └┘
pid                            └─┘                   
st   ───────────────────────────────────────────────────┘└┘
3882    { rw [pw_filter_cons_of_neg h],
id           └───────────────────┘ 
src      └──┘└───────────────────┘ 
typ      └──┘└───────────────────┘
doc      └──┘                      
txt      └──┘                      
par      └──┘                      
pid        └┘                      
st   ──────────────────────────────┘└──
3883      exact sublist_cons_of_sublist _ (pw_filter_sublist l) },
id             └─────────────────────┘    └───────────────┘ 
src      └────┘└─────────────────────┘└─┘                   └┘
typ      └────┘└─────────────────────┘└─┘ └───────────────┘└┘
doc      └────┘                       └─┘                   └┘
txt      └────┘                       └─┘                   └┘
par      └────┘                       └─┘                   └┘
pid                                  └─┘                   
st   ─────────────────────────────────────────────────────────┘└──
3884  end
st   ──┘
3885  
3886  theorem pw_filter_subset (l : list α) : pw_filter R l ⊆ l :=
id                                 └──┘     └───────┘    
src                                └──┘      └───────┘     
typ                                └──┘     └───────┘    
doc                                          └───────┘
3887  subset_of_sublist (pw_filter_sublist _)
id   └───────────────┘  └───────────────┘
src  └───────────────┘  └───────────────┘
typ  └───────────────┘  └───────────────┘
3888  
3889  theorem pairwise_pw_filter : ∀ (l : list α), pairwise R (pw_filter R l)
id                                      └──┘    └──────┘   └───────┘  
src                                      └──┘     └──────┘    └───────┘
typ                                     └──┘    └──────┘   └───────┘  
doc                                               └──────┘    └───────┘
3890  | []     := pairwise.nil
id     └┘        └──────────┘
src    └┘        └──────────┘
typ    └┘        └──────────┘
3891  | (x::l) := begin
id       └┘
src      └┘
typ      └┘
st               └─────
3892    by_cases (∀ y ∈ pw_filter R l, R x y),
id                     └───────┘      
src    └───────┘  └───┘└───────┘      
typ    └───────┘  └───┘└───────┘   
doc    └───────┘  └───┘└───────┘      
txt    └───────┘  └───┘               
par    └───────┘  └───┘               
pid              └───┘               
st   ──────────────────────────────────────┘└─
3893    { rw [pw_filter_cons_of_pos h],
id           └───────────────────┘ 
src      └──┘└───────────────────┘ 
typ      └──┘└───────────────────┘
doc      └──┘                      
txt      └──┘                      
par      └──┘                      
pid        └┘                      
st   ───┘└─────────────────────────┘└──
3894      exact pairwise_cons.2 ⟨h, pairwise_pw_filter l⟩ },
id             └───────────┘      └────────────────┘ 
src      └────┘└───────────┘└─┘  └┘                   └┘
typ      └────┘└───────────┘└─┘ └┘└────────────────┘└┘
doc      └────┘             └─┘  └┘                   └┘
txt      └────┘             └─┘  └┘                   └┘
par      └────┘             └─┘  └┘                   └┘
pid                        └─┘  └┘                   
st   ───────────────────────────────────────────────────┘└┘
3895    { rw [pw_filter_cons_of_neg h],
id           └───────────────────┘ 
src      └──┘└───────────────────┘ 
typ      └──┘└───────────────────┘
doc      └──┘                      
txt      └──┘                      
par      └──┘                      
pid        └┘                      
st   ──────────────────────────────┘└──
3896      exact pairwise_pw_filter l },
id             └────────────────┘ 
src      └────┘                   
typ      └────┘└────────────────┘
doc      └────┘                   
txt      └────┘                   
par      └────┘                   
pid                              
st   ──────────────────────────────┘└──
3897  end
st   ──┘
3898  
3899  theorem pw_filter_eq_self {l : list α} : pw_filter R l = l ↔ pairwise R l :=
id                                  └──┘     └───────┘      └──────┘  
src                                 └──┘      └───────┘         └──────┘
typ                                 └──┘     └───────┘      └──────┘  
doc                                           └───────┘           └──────┘
3900  ⟨λ e, e ▸ pairwise_pw_filter l, λ p, begin
id          └────────────────┘     
src           └────────────────┘
typ         └────────────────┘     
st                                        └─────
3901    induction l with x l IH, {refl},
id               
src    └────────┘ └──────────┘   └──┘
typ    └────────┘└──────────┘   └──┘
doc    └────────┘ └──────────┘   └──┘
txt    └────────┘ └──────────┘   └──┘
par    └────────┘ └──────────┘   └──┘
pid              └─────────┘
st   ────────────────────────┘└─────┘└┘
3902    cases pairwise_cons.1 p with al p,
id           └───────────┘   
src    └────┘└───────────┘└─┘ └────────┘
typ    └────┘└───────────┘└─┘└────────┘
doc    └────┘             └─┘ └────────┘
txt    └────┘             └─┘ └────────┘
par    └────┘             └─┘ └────────┘
pid                      └─┘ └────────┘
st   ──────────────────────────────────┘└─
3903    rw [pw_filter_cons_of_pos (ball.imp_left (pw_filter_subset l) al), IH p],
id         └───────────────────┘  └───────────┘  └──────────────┘   └┘   └┘ 
src    └──┘└───────────────────┘ └───────────┘ └──────────────┘ └┘  └─┘   
typ    └──┘└───────────────────┘ └───────────┘ └──────────────┘└┘└┘└─┘└┘
doc    └──┘                                                     └┘  └─┘   
txt    └──┘                                                     └┘  └─┘   
par    └──┘                                                     └┘  └─┘   
pid      └┘                                                     └┘  └─┘   
st   ──────────────────────────────────────────────────────────────────┘└────┘└──
3904  end⟩
st   ──┘
3905  
3906  @[simp] theorem pw_filter_idempotent {l : list α} :
id                                             └──┘ 
src                                            └──┘
typ                                            └──┘ 
doc    └──┘
3907    pw_filter R (pw_filter R l) = pw_filter R l :=
id     └───────┘   └───────┘     └───────┘  
src    └───────┘    └───────┘       └───────┘
typ    └───────┘   └───────┘     └───────┘  
doc    └───────┘    └───────┘        └───────┘
3908  pw_filter_eq_self.mpr (pairwise_pw_filter l)
id   └───────────────┘└──┘  └────────────────┘ 
src  └───────────────┘└──┘  └────────────────┘
typ  └───────────────┘└──┘  └────────────────┘ 
3909  
3910  theorem forall_mem_pw_filter (neg_trans : ∀ {x y z}, R x z → R x y ∨ R y z)
id                                                                
src                                                                     
typ                                                               
3911    (a : α) (l : list α) : (∀ b ∈ pw_filter R l, R a b) ↔ (∀ b ∈ l, R a b) :=
id                 └──┘           └───────┘                   
src                 └──┘             └───────┘             
typ                └──┘           └───────┘                   
doc                                  └───────┘
3912  ⟨begin
st    └─────
3913    induction l with x l IH, { exact λ _ _, false.elim },
id                                            └────────┘
src    └────────┘ └──────────┘    └────┘ └────┘└────────┘
typ    └────────┘└──────────┘    └────┘ └────┘└────────┘
doc    └────────┘ └──────────┘    └────┘ └────┘          
txt    └────────┘ └──────────┘    └────┘ └────┘          
par    └────────┘ └──────────┘    └────┘ └────┘          
pid              └─────────┘          └────┘          
st   ────────────────────────┘└──┘└──────────────────────┘└┘
3914    simp only [forall_mem_cons],
id                └─────────────┘
src    └─────────┘└─────────────┘
typ    └─────────┘└─────────────┘
doc    └─────────┘               
txt    └─────────┘               
par    └─────────┘               
pid        └──┘└┘               
st   ────────────────────────────┘└─
3915    by_cases (∀ y ∈ pw_filter R l, R x y); dsimp at h,
id                     └───────┘      
src    └───────┘  └───┘└───────┘        └────────┘
typ    └───────┘  └───┘└───────┘     └────────┘
doc    └───────┘  └───┘└───────┘        └────────┘
txt    └───────┘  └───┘                 └────────┘
par    └───────┘  └───┘                 └────────┘
pid              └───┘                      └──┘
st   ──────────────────────────────────────────────────┘└─
3916    { simp only [pw_filter_cons_of_pos h, forall_mem_cons, and_imp],
id                  └───────────────────┘   └─────────────┘  └─────┘
src      └─────────┘└───────────────────┘ └┘└─────────────┘└┘└─────┘
typ      └─────────┘└───────────────────┘└┘└─────────────┘└┘└─────┘
doc      └─────────┘                      └┘               └┘       
txt      └─────────┘                      └┘               └┘       
par      └─────────┘                      └┘               └┘       
pid          └──┘└┘                      └┘               └┘       
st   ───┘└───────────────────────────────────────────────────────────┘└─
3917      exact λ r H, ⟨r, IH H⟩ },
id                        └┘
src      └────┘ └────┘  └┘   └┘
typ      └────┘ └────┘  └┘└┘ └┘
doc      └────┘ └────┘  └┘   └┘
txt      └────┘ └────┘  └┘   └┘
par      └────┘ └────┘  └┘   └┘
pid            └────┘  └┘   
st   ──────────────────────────┘└┘
3918    { rw [pw_filter_cons_of_neg h],
id           └───────────────────┘ 
src      └──┘└───────────────────┘ 
typ      └──┘└───────────────────┘
doc      └──┘                      
txt      └──┘                      
par      └──┘                      
pid        └┘                      
st   ──────────────────────────────┘└──
3919      refine λ H, ⟨_, IH H⟩,
id                       └┘
src      └─────┘ └──┘ └─┘   
typ      └─────┘ └──┘ └─┘└┘ 
doc      └─────┘ └──┘ └─┘   
txt      └─────┘ └──┘ └─┘   
par      └─────┘ └──┘ └─┘   
pid             └──┘ └─┘   
st   ────────────────────────┘└─
3920      cases e : find (λ y, ¬ R x y) (pw_filter R l) with k,
id                 └──┘                └───────┘  
src      └────┘ └─┘└──┘  └──┘    └┘ └───────┘  └──────┘
typ      └────┘ └─┘└──┘  └──┘   └┘ └───────┘└──────┘
doc      └────┘ └─┘└──┘  └──┘    └┘ └───────┘  └──────┘
txt      └────┘ └─┘      └──┘    └┘            └──────┘
par      └────┘ └─┘      └──┘    └┘            └──────┘
pid            └─┘      └──┘    └┘            └─────┘
st   ───────────────────────────────────────────────────────┘└─
3921      { refine h.elim (ball.imp_right _ (find_eq_none.1 e)),
id                └────┘  └────────────┘    └──────────┘   
src        └─────┘└────┘ └────────────┘└─┘ └──────────┘└─┘ └┘
typ        └─────┘└────┘ └────────────┘└─┘ └──────────┘└─┘└┘
doc        └─────┘                     └─┘             └─┘ └┘
txt        └─────┘                     └─┘             └─┘ └┘
par        └─────┘                     └─┘             └─┘ └┘
pid                                   └─┘             └─┘ └┘
st   ─────┘└─────────────────────────────────────────────────┘└─
3922        exact λ y _, not_not.1 },
id                      └─────┘
src        └────┘ └────┘└─────┘└─┘
typ        └────┘ └────┘└─────┘└─┘
doc        └────┘ └────┘       └─┘
txt        └────┘ └────┘       └─┘
par        └────┘ └────┘       └─┘
pid              └────┘       └─┘
st   ────────────────────────────┘└┘
3923      { have := find_some e,
id                 └───────┘ 
src        └──────┘└───────┘
typ        └──────┘└───────┘
doc        └──────┘         
txt        └──────┘         
par        └──────┘         
pid        └───┘└─┘         
st   ────────────────────────┘└─
3924        exact (neg_trans (H k (find_mem e))).resolve_right this } }
id                └───────┘     └──────┘                   └──┘
src        └────┘              └──────┘ └────────────────┘    
typ        └────┘ └───────┘  └──────┘└────────────────┘└──┘
doc        └────┘                       └────────────────┘    
txt        └────┘                       └────────────────┘    
par        └────┘                       └────────────────┘    
pid                                    └────────────────┘    
st   ─────────────────────────────────────────────────────────────┘└───
3925  end, ball.imp_left (pw_filter_subset l)⟩
id        └───────────┘  └──────────────┘ 
src       └───────────┘  └──────────────┘
typ       └───────────┘  └──────────────┘ 
st   ──┘
3926  
3927  end pairwise
3928  
3929  /- chain relation (conjunction of R a b ∧ R b c ∧ R c d ...) -/
3930  
3931  section chain
3932  
3933  run_cmd tactic.mk_iff_of_inductive_prop `list.chain `list.chain_iff
id           └─────────────────────────────┘            
src          └─────────────────────────────┘            
typ          └─────────────────────────────┘            
doc          └─────────────────────────────┘
3934  
3935  variable {R : α → α → Prop}
3936  
3937  theorem rel_of_chain_cons {a b : α} {l : list α}
id                                           └──┘ 
src                                           └──┘
typ                                          └──┘ 
3938    (p : chain R a (b::l)) : R a b :=
id          └───┘    └┘       
src         └───┘       └┘
typ         └───┘    └┘       
doc         └───┘
3939  (chain_cons.1 p).1
id    └────────┘   
src   └────────┘    
typ   └────────┘   
3940  
3941  theorem chain_of_chain_cons {a b : α} {l : list α}
id                                             └──┘ 
src                                             └──┘
typ                                            └──┘ 
3942    (p : chain R a (b::l)) : chain R b l :=
id          └───┘    └┘     └───┘   
src         └───┘       └┘      └───┘
typ         └───┘    └┘     └───┘   
doc         └───┘               └───┘
3943  (chain_cons.1 p).2
id    └────────┘   
src   └────────┘    
typ   └────────┘   
3944  
3945  theorem chain.imp {S : α → α → Prop}
id                             
typ                            
3946    (H : ∀ a b, R a b → S a b) {a : α} {l : list α} (p : chain R a l) : chain S a l :=
id                                    └──┘        └───┘       └───┘   
src                                            └──┘         └───┘          └───┘
typ                                   └──┘        └───┘       └───┘   
doc                                                         └───┘          └───┘
3947  by induction p with _ a b l r p IH; constructor;
id                
src     └────────┘ └──────────────────┘  └─────────┘
typ     └────────┘└──────────────────┘  └─────────┘
doc     └────────┘ └──────────────────┘  └─────────┘
txt     └────────┘ └──────────────────┘  └─────────┘
par     └────────┘ └──────────────────┘  └─────────┘
pid               └─────────────────┘
st     └──────────────────────────────────────────────
3948     [exact H _ _ r, exact IH]
id                         └┘
src     └────┘ └───┘   └────┘
typ     └────┘└───┘  └────┘└┘
doc      └────┘ └───┘   └────┘
txt      └────┘ └───┘   └────┘
par      └────┘ └───┘   └────┘
pid            └───┘        
st   ───────────────────────────┘
3949  
3950  theorem chain.iff {S : α → α → Prop}
id                             
typ                            
3951    (H : ∀ a b, R a b ↔ S a b) {a : α} {l : list α} : chain R a l ↔ chain S a l :=
id                                   └──┘     └───┘     └───┘   
src                                           └──┘      └───┘        └───┘
typ                                  └──┘     └───┘     └───┘   
doc                                                      └───┘         └───┘
3952  ⟨chain.imp (λ a b, (H a b).1), chain.imp (λ a b, (H a b).2)⟩
id    └───────┘               └───────┘           
src   └───────┘                    └───────┘                
typ   └───────┘               └───────┘           
3953  
3954  theorem chain.iff_mem {a : α} {l : list α} :
id                                     └──┘ 
src                                     └──┘
typ                                    └──┘ 
3955    chain R a l ↔ chain (λ x y, x ∈ a :: l ∧ y ∈ l ∧ R x y) a l :=
id     └───┘     └───┘          └┘            
src    └───┘        └───┘              └┘         
typ    └───┘     └───┘          └┘            
doc    └───┘         └───┘
3956  ⟨λ p, by induction p with _ a b l r p IH; constructor;
id                     
src           └────────┘ └──────────────────┘  └─────────┘
typ          └────────┘└──────────────────┘  └─────────┘
doc           └────────┘ └──────────────────┘  └─────────┘
txt           └────────┘ └──────────────────┘  └─────────┘
par           └────────┘ └──────────────────┘  └─────────┘
pid                     └─────────────────┘
st           └──────────────────────────────────────────────
3957    [exact ⟨mem_cons_self _ _, mem_cons_self _ _, r⟩,
id                               └───────────┘      
src    └────┘              └────┘└───────────┘└────┘ 
typ    └────┘              └────┘└───────────┘└────┘
doc     └────┘              └────┘             └────┘ 
txt     └────┘              └────┘             └────┘ 
par     └────┘              └────┘             └────┘ 
pid                        └────┘             └────┘ 
st   ────────────────────────────────────────────────────
3958     exact IH.imp (λ a b ⟨am, bm, h⟩,
id            └────┘         └┘  └┘  
src     └────┘└────┘  └────┘  └┘  └┘ └──
typ     └────┘└────┘  └────┘└┘└┘└┘└┘└──
doc     └────┘        └────┘  └┘  └┘ └──
txt     └────┘        └────┘  └┘  └┘ └──
par     └────┘        └────┘  └┘  └┘ └──
pid                  └────┘  └┘  └┘ └──
st   ────────────────────────────────────
3959      ⟨mem_cons_of_mem _ am, mem_cons_of_mem _ bm, h⟩)],
id                              └─────────────┘
src  ───┘                └─┘  └┘└─────────────┘└─┘  └┘ └┘
typ  ───┘                └─┘  └┘└─────────────┘└─┘  └┘ └┘
doc  ───┘                └─┘  └┘               └─┘  └┘ └┘
txt  ───┘                └─┘  └┘               └─┘  └┘ └┘
par  ───┘                └─┘  └┘               └─┘  └┘ └┘
pid  ───┘                └─┘  └┘               └─┘  └┘ └┘
st   ────────────────────────────────────────────────────┘
3960   chain.imp (λ a b h, h.2.2)⟩
id    └───────┘         
src   └───────┘             
typ   └───────┘         
3961  
3962  theorem chain_singleton {a b : α} : chain R a [b] ↔ R a b :=
id                                      └───┘       
src                                      └───┘       
typ                                     └───┘       
doc                                      └───┘
3963  by simp only [chain_cons, chain.nil, and_true]
id                 └────────┘  └───────┘  └──────┘
src     └─────────┘└────────┘└┘└───────┘└┘└──────┘└─
typ     └─────────┘└────────┘└┘└───────┘└┘└──────┘└─
doc     └─────────┘          └┘         └┘        └─
txt     └─────────┘          └┘         └┘        └─
par     └─────────┘          └┘         └┘        └─
pid         └──┘└┘          └┘         └┘        
st     └────────────────────────────────────────────
3964  
src  
typ  
doc  
txt  
par  
pid  
st   
3965  theorem chain_split {a b : α} {l₁ l₂ : list α} : chain R a (l₁++b::l₂) ↔
id                                         └──┘     └───┘    └┘└┘└┘└┘  
src                                         └──┘      └───┘        └┘ └┘    
typ                                        └──┘     └───┘    └┘└┘└┘└┘  
doc                                                   └───┘
3966    chain R a (l₁++[b]) ∧ chain R b l₂ :=
id     └───┘    └┘└┘   └───┘   └┘
src    └───┘        └┘    └───┘
typ    └───┘    └┘└┘   └───┘   └┘
doc    └───┘                 └───┘
3967  by induction l₁ with x l₁ IH generalizing a;
id                └┘
src     └────────┘  └──────────────────────────┘
typ     └────────┘└┘└──────────────────────────┘
doc     └────────┘  └──────────────────────────┘
txt     └────────┘  └──────────────────────────┘
par     └────────┘  └──────────────────────────┘
pid                └──────────┘└─────────────┘
st     └──────────────────────────────────────────
3968  simp only [*, nil_append, cons_append, chain.nil, chain_cons, and_true, and_assoc]
id                 └────────┘  └─────────┘  └───────┘  └────────┘  └──────┘  └───────┘
src  └────────────┘└────────┘└┘└─────────┘└┘└───────┘└┘└────────┘└┘└──────┘└┘└───────┘└─
typ  └────────────┘└────────┘└┘└─────────┘└┘└───────┘└┘└────────┘└┘└──────┘└┘└───────┘└─
doc  └────────────┘          └┘           └┘         └┘          └┘        └┘         └─
txt  └────────────┘          └┘           └┘         └┘          └┘        └┘         └─
par  └────────────┘          └┘           └┘         └┘          └┘        └┘         └─
pid      └──┘└───┘          └┘           └┘         └┘          └┘        └┘         
st   ───────────────────────────────────────────────────────────────────────────────────
3969  
src  
typ  
doc  
txt  
par  
pid  
st   
3970  theorem chain_map (f : β → α) {b : β} {l : list β} :
id                                           └──┘ 
src                                             └──┘
typ                                          └──┘ 
3971    chain R (f b) (map f l) ↔ chain (λ a b : β, R (f a) (f b)) b l :=
id     └───┘       └─┘     └───┘                       
src    └───┘          └─┘       └───┘
typ    └───┘       └─┘     └───┘                       
doc    └───┘                     └───┘
3972  by induction l generalizing b; simp only [map, chain.nil, chain_cons, *]
id                                            └─┘  └───────┘  └────────┘
src     └────────┘ └─────────────┘  └─────────┘└─┘└┘└───────┘└┘└────────┘└────
typ     └────────┘└─────────────┘  └─────────┘└─┘└┘└───────┘└┘└────────┘└────
doc     └────────┘ └─────────────┘  └─────────┘   └┘         └┘          └────
txt     └────────┘ └─────────────┘  └─────────┘   └┘         └┘          └────
par     └────────┘ └─────────────┘  └─────────┘   └┘         └┘          └────
pid               └────────────┘      └──┘└┘   └┘         └┘          └──┘
st     └──────────────────────────────────────────────────────────────────────
3973  
src  
typ  
doc  
txt  
par  
pid  
st   
3974  theorem chain_of_chain_map {S : β → β → Prop} (f : α → β)
id                                                       
typ                                                      
3975    (H : ∀ a b : α, S (f a) (f b) → R a b) {a : α} {l : list α}
id                                               └──┘ 
src                                                        └──┘
typ                                              └──┘ 
3976    (p : chain S (f a) (map f l)) : chain R a l :=
id          └───┘       └─┘       └───┘   
src         └───┘          └─┘         └───┘
typ         └───┘       └─┘       └───┘   
doc         └───┘                      └───┘
3977  ((chain_map f).1 p).imp H
id     └───────┘     └─┘  
src    └───────┘       └─┘
typ    └───────┘     └─┘  
3978  
3979  theorem chain_map_of_chain {S : β → β → Prop} (f : α → β)
id                                                       
typ                                                      
3980    (H : ∀ a b : α, R a b → S (f a) (f b)) {a : α} {l : list α}
id                                               └──┘ 
src                                                        └──┘
typ                                              └──┘ 
3981    (p : chain R a l) : chain S (f a) (map f l) :=
id          └───┘       └───┘       └─┘  
src         └───┘          └───┘          └─┘
typ         └───┘       └───┘       └─┘  
doc         └───┘          └───┘
3982  (chain_map f).2 $ p.imp H
id    └───────┘      └──┘ 
src   └───────┘        └──┘
typ   └───────┘      └──┘ 
3983  
3984  theorem chain_of_pairwise {a : α} {l : list α} (p : pairwise R (a::l)) : chain R a l :=
id                                         └──┘        └──────┘   └┘     └───┘   
src                                         └──┘         └──────┘     └┘      └───┘
typ                                        └──┘        └──────┘   └┘     └───┘   
doc                                                      └──────┘             └───┘
3985  begin
st   └─────
3986    cases pairwise_cons.1 p with r p', clear p,
id           └───────────┘   
src    └────┘└───────────┘└─┘ └────────┘  └─────┘
typ    └────┘└───────────┘└─┘└────────┘  └─────┘
doc    └────┘             └─┘ └────────┘  └─────┘
txt    └────┘             └─┘ └────────┘  └─────┘
par    └────┘             └─┘ └────────┘  └─────┘
pid                      └─┘ └────────┘       └┘
st   ──────────────────────────────────┘└───────┘└─
3987    induction p' with b l r' p IH generalizing a, {exact chain.nil},
id               └┘                                         └───────┘
src    └────────┘  └──────────────────────────────┘   └────┘└───────┘
typ    └────────┘└┘└──────────────────────────────┘   └────┘└───────┘
doc    └────────┘  └──────────────────────────────┘   └────┘
txt    └────────┘  └──────────────────────────────┘   └────┘
par    └────────┘  └──────────────────────────────┘   └────┘
pid               └──────────────┘└─────────────┘        
st   ─────────────────────────────────────────────┘└────────────────┘└┘
3988    simp only [chain_cons, forall_mem_cons] at r,
id                └────────┘  └─────────────┘
src    └─────────┘└────────┘└┘└─────────────┘└────┘
typ    └─────────┘└────────┘└┘└─────────────┘└────┘
doc    └─────────┘          └┘               └────┘
txt    └─────────┘          └┘               └────┘
par    └─────────┘          └┘               └────┘
pid        └──┘└┘          └┘               └──┘
st   ─────────────────────────────────────────────┘└─
3989    exact chain_cons.2 ⟨r.1, IH r'⟩
id           └────────┘        └┘ └┘
src    └────┘└────────┘└─┘  └──┘    └┘
typ    └────┘└────────┘└─┘ └──┘└┘└┘└┘
doc    └────┘          └─┘  └──┘    └┘
txt    └────┘          └─┘  └──┘    └┘
par    └────┘          └─┘  └──┘    └┘
pid                   └─┘  └──┘    
st   ─────────────────────────────────┘
3990  end
st   └─┘
3991  
3992  theorem chain_iff_pairwise (tr : transitive R) {a : α} {l : list α} :
id                                    └────────┘               └──┘ 
src                                   └────────┘                 └──┘
typ                                   └────────┘               └──┘ 
3993    chain R a l ↔ pairwise R (a::l) :=
id     └───┘     └──────┘   └┘
src    └───┘        └──────┘     └┘
typ    └───┘     └──────┘   └┘
doc    └───┘         └──────┘
3994  ⟨λ c, begin
id      
typ     
st         └─────
3995    induction c with b b c l r p IH, {exact pairwise_singleton _ _},
id                                            └────────────────┘
src    └────────┘ └──────────────────┘   └────┘└────────────────┘└──┘
typ    └────────┘└──────────────────┘   └────┘└────────────────┘└──┘
doc    └────────┘ └──────────────────┘   └────┘                  └──┘
txt    └────────┘ └──────────────────┘   └────┘                  └──┘
par    └────────┘ └──────────────────┘   └────┘                  └──┘
pid              └─────────────────┘                          └──┘
st   ────────────────────────────────┘└─────────────────────────────┘└┘
3996    apply IH.cons _, simp only [mem_cons_iff, forall_mem_cons', r, true_and],
id           └─────┘               └──────────┘  └──────────────┘    └──────┘
src    └────┘└─────┘└┘  └─────────┘└──────────┘└┘└──────────────┘└┘ └┘└──────┘
typ    └────┘└─────┘└┘  └─────────┘└──────────┘└┘└──────────────┘└┘└┘└──────┘
doc    └────┘       └┘  └─────────┘            └┘                └┘ └┘        
txt    └────┘       └┘  └─────────┘            └┘                └┘ └┘        
par    └────┘       └┘  └─────────┘            └┘                └┘ └┘        
pid                └┘      └──┘└┘            └┘                └┘ └┘        
st   ────────────────┘└───────────────────────────────────────────────────────┘└─
3997    show ∀ x ∈ l, R b x, from λ x m, (tr r (rel_of_pairwise_cons IH m)),
id                                    └┘   └──────────────────┘ └┘
src    └───┘ └───┘       └───┘ └────┘     └──────────────────┘   └┘
typ    └───┘ └───┘    └───┘ └────┘ └┘ └──────────────────┘└┘ └┘
doc    └───┘ └───┘       └───┘ └────┘                            └┘
txt    └───┘ └───┘       └───┘ └────┘                            └┘
par    └───┘ └───┘       └───┘ └────┘                            └┘
pid    └───┘ └───┘       └───┘ └────┘                            └┘
st   ────────────────────────────────────────────────────────────────────┘└─
3998  end, chain_of_pairwise⟩
id        └───────────────┘
src       └───────────────┘
typ       └───────────────┘
st   ──┘
3999  
4000  theorem chain'.imp {S : α → α → Prop}
id                              
typ                             
4001    (H : ∀ a b, R a b → S a b) {l : list α} (p : chain' R l) : chain' S l :=
id                             └──┘        └────┘      └────┘  
src                                    └──┘         └────┘        └────┘
typ                            └──┘        └────┘      └────┘  
doc                                                 └────┘        └────┘
4002  by cases l; [trivial, exact p.imp H]
id                             └───┘ 
src     └────┘   └─────┘  └────┘└───┘
typ     └────┘  └─────┘  └────┘└───┘
doc     └────┘    └─────┘  └────┘     
txt     └────┘    └─────┘  └────┘     
par     └────┘    └─────┘  └────┘     
pid                                 
st     └────────────────────────────────┘
4003  
4004  theorem chain'.iff {S : α → α → Prop}
id                              
typ                             
4005    (H : ∀ a b, R a b ↔ S a b) {l : list α} : chain' R l ↔ chain' S l :=
id                            └──┘     └────┘    └────┘  
src                                   └──┘      └────┘      └────┘
typ                           └──┘     └────┘    └────┘  
doc                                              └────┘       └────┘
4006  ⟨chain'.imp (λ a b, (H a b).1), chain'.imp (λ a b, (H a b).2)⟩
id    └────────┘               └────────┘           
src   └────────┘                    └────────┘                
typ   └────────┘               └────────┘           
4007  
4008  theorem chain'.iff_mem : ∀ {l : list α}, chain' R l ↔ chain' (λ x y, x ∈ l ∧ y ∈ l ∧ R x y) l
id                                  └──┘    └────┘    └────┘                   
src                                  └──┘     └────┘      └────┘                    
typ                                 └──┘    └────┘    └────┘                   
doc                                           └────┘       └────┘
4009  | [] := iff.rfl
id     └┘    └─────┘
src    └┘    └─────┘
typ    └┘    └─────┘
4010  | (x::l) :=
id       └┘
src      └┘
typ      └┘
4011    ⟨λ h, (chain.iff_mem.1 h).imp $ λ a b ⟨h₁, h₂, h₃⟩, ⟨h₁, or.inr h₂, h₃⟩,
id           └───────────┘   └─┘        └┘  └┘  └┘        └────┘
src           └───────────┘    └─┘                             └────┘
typ          └───────────┘   └─┘        └┘  └┘  └┘        └────┘
4012     chain'.imp $ λ a b h, h.2.2⟩
id      └────────┘          
src     └────────┘              
typ     └────────┘          
4013  
4014  theorem chain'_singleton (a : α) : chain' R [a] := chain.nil
id                                     └────┘      └───────┘
src                                     └────┘        └───────┘
typ                                    └────┘      └───────┘
doc                                     └────┘
4015  
4016  theorem chain'_split {a : α} : ∀ {l₁ l₂ : list α}, chain' R (l₁++a::l₂) ↔
id                                           └──┘    └────┘   └┘└┘└┘└┘  
src                                            └──┘     └────┘      └┘ └┘    
typ                                          └──┘    └────┘   └┘└┘└┘└┘  
doc                                                     └────┘
4017    chain' R (l₁++[a]) ∧ chain' R (a::l₂)
id     └────┘   └┘└┘   └────┘   └┘└┘
src    └────┘      └┘    └────┘     └┘
typ    └────┘   └┘└┘   └────┘   └┘└┘
doc    └────┘               └────┘
4018  | []      l₂ := (and_iff_right (chain'_singleton a)).symm
id     └┘             └───────────┘  └──────────────┘   └──┘
src    └┘             └───────────┘  └──────────────┘    └──┘
typ    └┘             └───────────┘  └──────────────┘   └──┘
4019  | (b::l₁) l₂ := chain_split
id       └┘          └─────────┘
src      └┘          └─────────┘
typ      └┘          └─────────┘
4020  
4021  theorem chain'_map (f : β → α) {l : list β} :
id                                     └──┘ 
src                                      └──┘
typ                                    └──┘ 
4022    chain' R (map f l) ↔ chain' (λ a b : β, R (f a) (f b)) l :=
id     └────┘   └─┘     └────┘                      
src    └────┘    └─┘       └────┘
typ    └────┘   └─┘     └────┘                      
doc    └────┘               └────┘
4023  by cases l; [refl, exact chain_map _]
id                          └───────┘
src     └────┘   └──┘  └────┘└───────┘└┘
typ     └────┘  └──┘  └────┘└───────┘└┘
doc     └────┘    └──┘  └────┘         └┘
txt     └────┘    └──┘  └────┘         └┘
par     └────┘    └──┘  └────┘         └┘
pid                                  └┘
st     └─────────────────────────────────┘
4024  
4025  theorem chain'_of_chain'_map {S : β → β → Prop} (f : α → β)
id                                                         
typ                                                        
4026    (H : ∀ a b : α, S (f a) (f b) → R a b) {l : list α}
id                                        └──┘ 
src                                                └──┘
typ                                       └──┘ 
4027    (p : chain' S (map f l)) : chain' R l :=
id          └────┘   └─┘       └────┘  
src         └────┘    └─┘         └────┘
typ         └────┘   └─┘       └────┘  
doc         └────┘                └────┘
4028  ((chain'_map f).1 p).imp H
id     └────────┘     └─┘  
src    └────────┘       └─┘
typ    └────────┘     └─┘  
4029  
4030  theorem chain'_map_of_chain' {S : β → β → Prop} (f : α → β)
id                                                         
typ                                                        
4031    (H : ∀ a b : α, R a b → S (f a) (f b)) {l : list α}
id                                        └──┘ 
src                                                └──┘
typ                                       └──┘ 
4032    (p : chain' R l) : chain' S (map f l) :=
id          └────┘      └────┘   └─┘  
src         └────┘        └────┘    └─┘
typ         └────┘      └────┘   └─┘  
doc         └────┘        └────┘
4033  (chain'_map f).2 $ p.imp H
id    └────────┘      └──┘ 
src   └────────┘        └──┘
typ   └────────┘      └──┘ 
4034  
4035  theorem chain'_of_pairwise : ∀ {l : list α}, pairwise R l → chain' R l
id                                      └──┘    └──────┘     └────┘  
src                                      └──┘     └──────┘       └────┘
typ                                     └──┘    └──────┘     └────┘  
doc                                               └──────┘       └────┘
4036  | [] _ := trivial
id     └┘      └─────┘
src    └┘      └─────┘
typ    └┘      └─────┘
4037  | (a::l) h := chain_of_pairwise h
id       └┘       └───────────────┘
src      └┘        └───────────────┘
typ      └┘       └───────────────┘
4038  
4039  theorem chain'_iff_pairwise (tr : transitive R) : ∀ {l : list α},
id                                     └────────┘           └──┘ 
src                                    └────────┘             └──┘
typ                                    └────────┘           └──┘ 
4040    chain' R l ↔ pairwise R l
id     └────┘    └──────┘  
src    └────┘      └──────┘
typ    └────┘    └──────┘  
doc    └────┘       └──────┘
4041  | [] := (iff_true_intro pairwise.nil).symm
id     └┘     └────────────┘ └──────────┘ └──┘
src    └┘     └────────────┘ └──────────┘ └──┘
typ    └┘     └────────────┘ └──────────┘ └──┘
4042  | (a::l) := chain_iff_pairwise tr
id       └┘      └────────────────┘ └┘
src      └┘      └────────────────┘
typ      └┘      └────────────────┘ └┘
4043  
4044  end chain
4045  
4046  /- no duplicates predicate -/
4047  
4048  section nodup
4049  
4050  @[simp] theorem forall_mem_ne {a : α} {l : list α} : (∀ (a' : α), a' ∈ l → ¬a = a') ↔ a ∉ l :=
id                                             └──┘                 └┘       └┘     
src                                             └──┘                                     
typ                                            └──┘                 └┘       └┘     
doc    └──┘
4051  ⟨λ h m, h _ m rfl, λ h a' m e, h (e.symm ▸ m)⟩
id             └─┘     └┘      └───┘  
src                └─┘                  └───┘ 
typ            └─┘     └┘      └───┘  
4052  
4053  @[simp] theorem nodup_nil : @nodup α [] := pairwise.nil
id                                └───┘  └┘    └──────────┘
src                               └───┘   └┘    └──────────┘
typ                               └───┘  └┘    └──────────┘
doc    └──┘                       └───┘
4054  
4055  @[simp] theorem nodup_cons {a : α} {l : list α} : nodup (a::l) ↔ a ∉ l ∧ nodup l :=
id                                          └──┘     └───┘  └┘       └───┘ 
src                                          └──┘      └───┘   └┘          └───┘
typ                                         └──┘     └───┘  └┘       └───┘ 
doc    └──┘                                            └───┘                  └───┘
4056  by simp only [nodup, pairwise_cons, forall_mem_ne]
id                 └───┘  └───────────┘  └───────────┘
src     └─────────┘└───┘└┘└───────────┘└┘└───────────┘└─
typ     └─────────┘└───┘└┘└───────────┘└┘└───────────┘└─
doc     └─────────┘└───┘└┘             └┘             └─
txt     └─────────┘     └┘             └┘             └─
par     └─────────┘     └┘             └┘             └─
pid         └──┘└┘     └┘             └┘             
st     └────────────────────────────────────────────────
4057  
src  
typ  
doc  
txt  
par  
pid  
st   
4058  lemma rel_nodup {r : α → β → Prop} (hr : relator.bi_unique r) : (forall₂ r ⇒ (↔)) nodup nodup
id                                          └───────────────┘      └─────┘       └───┘ └───┘
src                                           └───────────────┘       └─────┘        └───┘ └───┘
typ                                         └───────────────┘      └─────┘       └───┘ └───┘
doc                                                                                    └───┘ └───┘
4059  | _ _ forall₂.nil      := by simp only [nodup_nil]
id         └─────────┘                       └───────┘
src        └─────────┘            └─────────┘└───────┘└┘
typ        └─────────┘            └─────────┘└───────┘└┘
doc                               └─────────┘         └┘
txt                               └─────────┘         └┘
par                               └─────────┘         └┘
pid                                   └──┘└┘         
st                               └─────────────────────┘
4060  | _ _ (forall₂.cons hab h) :=
id          └──────────┘
src         └──────────┘
typ         └──────────┘
4061    by simpa only [nodup_cons] using relator.rel_and (relator.rel_not (rel_mem hr hab h)) (rel_nodup h)
id                    └────────┘        └─────────────┘  └─────────────┘  └─────┘ └┘ └─┘      └───────┘ 
src       └──────────┘└────────┘└──────┘└─────────────┘ └─────────────┘ └─────┘      └─┘           └─
typ       └──────────┘└────────┘└──────┘└─────────────┘ └─────────────┘ └─────┘└┘└─┘ └─┘ └───────┘└─
doc       └──────────┘          └──────┘                                             └─┘           └─
txt       └──────────┘          └──────┘                                             └─┘           └─
par       └──────────┘          └──────┘                                             └─┘           └─
pid            └──┘└┘          └────┘                                             └─┘           
st       └─────────────────────────────────────────────────────────────────────────────────────────────────
4062  
src  
typ  
doc  
txt  
par  
pid  
st   
4063  theorem nodup_cons_of_nodup {a : α} {l : list α} (m : a ∉ l) (n : nodup l) : nodup (a::l) :=
id                                           └──┘                 └───┘     └───┘  └┘
src                                           └──┘                    └───┘      └───┘   └┘
typ                                          └──┘                 └───┘     └───┘  └┘
doc                                                                    └───┘      └───┘
4064  nodup_cons.2 ⟨m, n⟩
id   └────────┘     
src  └────────┘
typ  └────────┘     
4065  
4066  theorem nodup_singleton (a : α) : nodup [a] :=
id                                    └───┘ 
src                                    └───┘  
typ                                   └───┘ 
doc                                    └───┘
4067  nodup_cons_of_nodup (not_mem_nil a) nodup_nil
id   └─────────────────┘  └─────────┘   └───────┘
src  └─────────────────┘  └─────────┘    └───────┘
typ  └─────────────────┘  └─────────┘   └───────┘
4068  
4069  theorem nodup_of_nodup_cons {a : α} {l : list α} (h : nodup (a::l)) : nodup l :=
id                                           └──┘        └───┘  └┘     └───┘ 
src                                           └──┘         └───┘   └┘      └───┘
typ                                          └──┘        └───┘  └┘     └───┘ 
doc                                                        └───┘           └───┘
4070  (nodup_cons.1 h).2
id    └────────┘   
src   └────────┘    
typ   └────────┘   
4071  
4072  theorem not_mem_of_nodup_cons {a : α} {l : list α} (h : nodup (a::l)) : a ∉ l :=
id                                             └──┘        └───┘  └┘       
src                                             └──┘         └───┘   └┘        
typ                                            └──┘        └───┘  └┘       
doc                                                          └───┘
4073  (nodup_cons.1 h).1
id    └────────┘   
src   └────────┘    
typ   └────────┘   
4074  
4075  theorem not_nodup_cons_of_mem {a : α} {l : list α} : a ∈ l → ¬ nodup (a :: l) :=
id                                             └──┘           └───┘   └┘ 
src                                             └──┘              └───┘    └┘
typ                                            └──┘           └───┘   └┘ 
doc                                                                 └───┘
4076  imp_not_comm.1 not_mem_of_nodup_cons
id   └──────────┘  └───────────────────┘
src  └──────────┘  └───────────────────┘
typ  └──────────┘  └───────────────────┘
4077  
4078  theorem nodup_of_sublist {l₁ l₂ : list α} : l₁ <+ l₂ → nodup l₂ → nodup l₁ :=
id                                     └──┘     └┘ └┘ └┘   └───┘ └┘   └───┘ └┘
src                                    └──┘         └┘      └───┘      └───┘
typ                                    └──┘     └┘ └┘ └┘   └───┘ └┘   └───┘ └┘
doc                                                         └───┘      └───┘
4079  pairwise_of_sublist
id   └─────────────────┘
src  └─────────────────┘
typ  └─────────────────┘
4080  
4081  theorem not_nodup_pair (a : α) : ¬ nodup [a, a] :=
id                                    └───┘  
src                                    └───┘    
typ                                   └───┘  
doc                                     └───┘
4082  not_nodup_cons_of_mem $ mem_singleton_self _
id   └───────────────────┘   └────────────────┘
src  └───────────────────┘   └────────────────┘
typ  └───────────────────┘   └────────────────┘
4083  
4084  theorem nodup_iff_sublist {l : list α} : nodup l ↔ ∀ a, ¬ [a, a] <+ l :=
id                                  └──┘     └───┘          └┘ 
src                                 └──┘      └───┘              └┘
typ                                 └──┘     └───┘          └┘ 
doc                                           └───┘
4085  ⟨λ d a h, not_nodup_pair a (nodup_of_sublist h d), begin
id          └────────────┘   └──────────────┘  
src            └────────────┘    └──────────────┘
typ         └────────────┘   └──────────────┘  
st                                                      └─────
4086    induction l with a l IH; intro h, {exact nodup_nil},
id                                             └───────┘
src    └────────┘ └──────────┘  └─────┘   └────┘└───────┘
typ    └────────┘└──────────┘  └─────┘   └────┘└───────┘
doc    └────────┘ └──────────┘  └─────┘   └────┘
txt    └────────┘ └──────────┘  └─────┘   └────┘
par    └────────┘ └──────────┘  └─────┘   └────┘
pid              └─────────┘       └┘        
st   ─────────────────────────────────┘└────────────────┘└┘
4087    exact nodup_cons_of_nodup
id           └─────────────────┘
src    └────┘└─────────────────┘
typ    └────┘└─────────────────┘
doc    └────┘                   
txt    └────┘                   
par    └────┘                   
pid                            
st   ────────────────────────────
4088      (λ al, h a $ cons_sublist_cons _ $ singleton_sublist.2 al)
id                   └───────────────┘     └───────────────┘
src  ───┘  └───┘   └───────────────┘└─┘ └───────────────┘└─┘  └─
typ  ───┘  └───┘  └───────────────┘└─┘ └───────────────┘└─┘  └─
doc  ───┘  └───┘                    └─┘                  └─┘  └─
txt  ───┘  └───┘                    └─┘                  └─┘  └─
par  ───┘  └───┘                    └─┘                  └─┘  └─
pid  ───┘  └───┘                    └─┘                  └─┘  └─
st   ───────────────────────────────────────────────────────────────
4089      (IH $ λ a s, h a $ sublist_cons_of_sublist _ s)
id        └┘               └─────────────────────┘
src  ───┘     └────┘   └─────────────────────┘└─┘ └┘
typ  ───┘ └┘  └────┘  └─────────────────────┘└─┘ └┘
doc  ───┘     └────┘                          └─┘ └┘
txt  ───┘     └────┘                          └─┘ └┘
par  ───┘     └────┘                          └─┘ └┘
pid  ───┘     └────┘                          └─┘ 
st   ───────────────────────────────────────────────────┘
4090  end⟩
st   └─┘
4091  
4092  theorem nodup_iff_nth_le_inj {l : list α} :
id                                     └──┘ 
src                                    └──┘
typ                                    └──┘ 
4093    nodup l ↔ ∀ i j h₁ h₂, nth_le l i h₁ = nth_le l j h₂ → i = j :=
id     └───┘       └┘ └┘  └────┘   └┘  └────┘   └┘     
src    └───┘                 └────┘         └────┘            
typ    └───┘       └┘ └┘  └────┘   └┘  └────┘   └┘     
doc    └───┘
4094  pairwise_iff_nth_le.trans
id   └─────────────────┘└────┘
src  └─────────────────┘└────┘
typ  └─────────────────┘└────┘
4095  ⟨λ H i j h₁ h₂ h, ((lt_trichotomy _ _)
id         └┘ └┘     └───────────┘
src                      └───────────┘
typ        └┘ └┘     └───────────┘
4096    .resolve_left (λ h', H _ _ h₂ h' h))
id     └──────────┘     └┘       └┘ └┘ 
src    └──────────┘
typ    └──────────┘     └┘       └┘ └┘ 
4097    .resolve_right (λ h', H _ _ h₁ h' h.symm),
id     └───────────┘     └┘       └┘ └┘ └───┘
src    └───────────┘                      └───┘
typ    └───────────┘     └┘       └┘ └┘ └───┘
4098   λ H i j h₁ h₂ h, ne_of_lt h₂ (H _ _ _ _ h)⟩
id         └┘ └┘   └──────┘ └┘           
src                    └──────┘
typ        └┘ └┘   └──────┘ └┘           
4099  
4100  @[simp] theorem nth_le_index_of [decidable_eq α] {l : list α} (H : nodup l) (n h) : index_of (nth_le l n h) l = n :=
id                                    └──────────┘        └──┘        └───┘           └──────┘  └────┘       
src                                   └──────────┘         └──┘         └───┘            └──────┘  └────┘          
typ                                   └──────────┘        └──┘        └───┘           └──────┘  └────┘       
doc    └──┘                                                             └───┘
4101  nodup_iff_nth_le_inj.1 H _ _ _ h $
id   └──────────────────┘         
src  └──────────────────┘
typ  └──────────────────┘         
4102  index_of_nth_le $ index_of_lt_length.2 $ nth_le_mem _ _ _
id   └─────────────┘   └────────────────┘    └────────┘
src  └─────────────┘   └────────────────┘    └────────┘
typ  └─────────────┘   └────────────────┘    └────────┘
4103  
4104  theorem nodup_iff_count_le_one [decidable_eq α] {l : list α} : nodup l ↔ ∀ a, count a l ≤ 1 :=
id                                   └──────────┘        └──┘     └───┘       └───┘   
src                                  └──────────┘         └──┘      └───┘         └───┘     
typ                                  └──────────┘        └──┘     └───┘       └───┘   
doc                                                                 └───┘          └───┘
4105  nodup_iff_sublist.trans $ forall_congr $ λ a,
id   └───────────────┘└────┘   └──────────┘     
src  └───────────────┘└────┘   └──────────┘
typ  └───────────────┘└────┘   └──────────┘     
4106  have [a, a] <+ l ↔ 1 < count a l, from (@le_count_iff_repeat_sublist _ _ a l 2).symm,
id          └┘      └───┘           └─────────────────────────┘         └──┘
src           └┘       └───┘             └─────────────────────────┘           └──┘
typ         └┘      └───┘           └─────────────────────────┘         └──┘
doc                         └───┘
4107  (not_congr this).trans not_lt
id    └───────┘ └──┘ └───┘  └────┘
src   └───────┘      └───┘  └────┘
typ   └───────┘ └──┘ └───┘  └────┘
4108  
4109  theorem nodup_repeat (a : α) : ∀ {n : ℕ}, nodup (repeat a n) ↔ n ≤ 1
id                                          └───┘  └────┘      
src                                           └───┘  └────┘         
typ                                         └───┘  └────┘      
doc                                            └───┘
4110  | 0 := by simp [nat.zero_le]
id                   └─────────┘
src            └────┘└─────────┘└┘
typ            └────┘└─────────┘└┘
doc            └────┘           └┘
txt            └────┘           └┘
par            └────┘           └┘
pid                           
st            └──────────────────┘
4111  | 1 := by simp
src            └───┘
typ            └───┘
doc            └───┘
txt            └───┘
par            └───┘
pid                
st            └────┘
4112  | (n+2) := iff_of_false
id            └──────────┘
src            └──────────┘
typ           └──────────┘
4113    (λ H, nodup_iff_sublist.1 H a ((repeat_sublist_repeat _).2 (le_add_left 2 n)))
id          └───────────────┘      └───────────────────┘      └─────────┘
src          └───────────────┘        └───────────────────┘      └─────────┘
typ         └───────────────┘      └───────────────────┘      └─────────┘
4114    (not_le_of_lt $ le_add_left 2 n)
id      └──────────┘   └─────────┘
src     └──────────┘   └─────────┘
typ     └──────────┘   └─────────┘
4115  
4116  @[simp] theorem count_eq_one_of_mem [decidable_eq α] {a : α} {l : list α}
id                                        └──────────┘               └──┘ 
src                                       └──────────┘                 └──┘
typ                                       └──────────┘               └──┘ 
doc    └──┘
4117    (d : nodup l) (h : a ∈ l) : count a l = 1 :=
id          └───┘              └───┘   
src         └───┘                 └───┘     
typ         └───┘              └───┘   
doc         └───┘                  └───┘
4118  le_antisymm (nodup_iff_count_le_one.1 d a) (count_pos.2 h)
id   └─────────┘  └────────────────────┘      └───────┘  
src  └─────────┘  └────────────────────┘        └───────┘
typ  └─────────┘  └────────────────────┘      └───────┘  
4119  
4120  theorem nodup_of_nodup_append_left {l₁ l₂ : list α} : nodup (l₁++l₂) → nodup l₁ :=
id                                               └──┘     └───┘  └┘└┘└┘    └───┘ └┘
src                                              └──┘      └───┘    └┘      └───┘
typ                                              └──┘     └───┘  └┘└┘└┘    └───┘ └┘
doc                                                        └───┘            └───┘
4121  nodup_of_sublist (sublist_append_left l₁ l₂)
id   └──────────────┘  └─────────────────┘ └┘ └┘
src  └──────────────┘  └─────────────────┘
typ  └──────────────┘  └─────────────────┘ └┘ └┘
4122  
4123  theorem nodup_of_nodup_append_right {l₁ l₂ : list α} : nodup (l₁++l₂) → nodup l₂ :=
id                                                └──┘     └───┘  └┘└┘└┘    └───┘ └┘
src                                               └──┘      └───┘    └┘      └───┘
typ                                               └──┘     └───┘  └┘└┘└┘    └───┘ └┘
doc                                                         └───┘            └───┘
4124  nodup_of_sublist (sublist_append_right l₁ l₂)
id   └──────────────┘  └──────────────────┘ └┘ └┘
src  └──────────────┘  └──────────────────┘
typ  └──────────────┘  └──────────────────┘ └┘ └┘
4125  
4126  theorem nodup_append {l₁ l₂ : list α} : nodup (l₁++l₂) ↔ nodup l₁ ∧ nodup l₂ ∧ disjoint l₁ l₂ :=
id                                 └──┘     └───┘  └┘└┘└┘   └───┘ └┘  └───┘ └┘  └──────┘ └┘ └┘
src                                └──┘      └───┘    └┘     └───┘     └───┘     └──────┘
typ                                └──┘     └───┘  └┘└┘└┘   └───┘ └┘  └───┘ └┘  └──────┘ └┘ └┘
doc                                          └───┘            └───┘      └───┘      └──────┘
4127  by simp only [nodup, pairwise_append, disjoint_iff_ne]
id                 └───┘  └─────────────┘  └─────────────┘
src     └─────────┘└───┘└┘└─────────────┘└┘└─────────────┘└─
typ     └─────────┘└───┘└┘└─────────────┘└┘└─────────────┘└─
doc     └─────────┘└───┘└┘               └┘               └─
txt     └─────────┘     └┘               └┘               └─
par     └─────────┘     └┘               └┘               └─
pid         └──┘└┘     └┘               └┘               
st     └────────────────────────────────────────────────────
4128  
src  
typ  
doc  
txt  
par  
pid  
st   
4129  theorem disjoint_of_nodup_append {l₁ l₂ : list α} (d : nodup (l₁++l₂)) : disjoint l₁ l₂ :=
id                                             └──┘        └───┘  └┘└┘└┘     └──────┘ └┘ └┘
src                                            └──┘         └───┘    └┘       └──────┘
typ                                            └──┘        └───┘  └┘└┘└┘     └──────┘ └┘ └┘
doc                                                         └───┘             └──────┘
4130  (nodup_append.1 d).2.2
id    └──────────┘    
src   └──────────┘     
typ   └──────────┘    
4131  
4132  theorem nodup_append_of_nodup {l₁ l₂ : list α} (d₁ : nodup l₁) (d₂ : nodup l₂)
id                                          └──┘         └───┘ └┘        └───┘ └┘
src                                         └──┘          └───┘           └───┘
typ                                         └──┘         └───┘ └┘        └───┘ └┘
doc                                                       └───┘           └───┘
4133    (dj : disjoint l₁ l₂) : nodup (l₁++l₂) :=
id           └──────┘ └┘ └┘    └───┘  └┘└┘└┘
src          └──────┘          └───┘    └┘
typ          └──────┘ └┘ └┘    └───┘  └┘└┘└┘
doc          └──────┘          └───┘
4134  nodup_append.2 ⟨d₁, d₂, dj⟩
id   └──────────┘   └┘  └┘  └┘
src  └──────────┘
typ  └──────────┘   └┘  └┘  └┘
4135  
4136  theorem nodup_append_comm {l₁ l₂ : list α} : nodup (l₁++l₂) ↔ nodup (l₂++l₁) :=
id                                      └──┘     └───┘  └┘└┘└┘   └───┘  └┘└┘└┘
src                                     └──┘      └───┘    └┘     └───┘    └┘
typ                                     └──┘     └───┘  └┘└┘└┘   └───┘  └┘└┘└┘
doc                                               └───┘            └───┘
4137  by simp only [nodup_append, and.left_comm, disjoint_comm]
id                 └──────────┘  └───────────┘  └───────────┘
src     └─────────┘└──────────┘└┘└───────────┘└┘└───────────┘└─
typ     └─────────┘└──────────┘└┘└───────────┘└┘└───────────┘└─
doc     └─────────┘            └┘             └┘             └─
txt     └─────────┘            └┘             └┘             └─
par     └─────────┘            └┘             └┘             └─
pid         └──┘└┘            └┘             └┘             
st     └───────────────────────────────────────────────────────
4138  
src  
typ  
doc  
txt  
par  
pid  
st   
4139  theorem nodup_middle {a : α} {l₁ l₂ : list α} : nodup (l₁ ++ a::l₂) ↔ nodup (a::(l₁++l₂)) :=
id                                        └──┘     └───┘  └┘ └┘ └┘└┘   └───┘  └┘ └┘└┘└┘
src                                        └──┘      └───┘     └┘  └┘     └───┘   └┘   └┘
typ                                       └──┘     └───┘  └┘ └┘ └┘└┘   └───┘  └┘ └┘└┘└┘
doc                                                  └───┘                 └───┘
4140  by simp only [nodup_append, not_or_distrib, and.left_comm, and_assoc, nodup_cons, mem_append, disjoint_cons_right]
id                 └──────────┘  └────────────┘  └───────────┘  └───────┘  └────────┘  └────────┘  └─────────────────┘
src     └─────────┘└──────────┘└┘└────────────┘└┘└───────────┘└┘└───────┘└┘└────────┘└┘└────────┘└┘└─────────────────┘└─
typ     └─────────┘└──────────┘└┘└────────────┘└┘└───────────┘└┘└───────┘└┘└────────┘└┘└────────┘└┘└─────────────────┘└─
doc     └─────────┘            └┘              └┘             └┘         └┘          └┘          └┘                   └─
txt     └─────────┘            └┘              └┘             └┘         └┘          └┘          └┘                   └─
par     └─────────┘            └┘              └┘             └┘         └┘          └┘          └┘                   └─
pid         └──┘└┘            └┘              └┘             └┘         └┘          └┘          └┘                   
st     └────────────────────────────────────────────────────────────────────────────────────────────────────────────────
4141  
src  
typ  
doc  
txt  
par  
pid  
st   
4142  theorem nodup_of_nodup_map (f : α → β) {l : list α} : nodup (map f l) → nodup l :=
id                                             └──┘     └───┘  └─┘      └───┘ 
src                                              └──┘      └───┘  └─┘        └───┘
typ                                            └──┘     └───┘  └─┘      └───┘ 
doc                                                        └───┘             └───┘
4143  pairwise_of_pairwise_map f $ λ a b, mt $ congr_arg f
id   └──────────────────────┘         └┘   └───────┘ 
src  └──────────────────────┘            └┘   └───────┘
typ  └──────────────────────┘         └┘   └───────┘ 
4144  
4145  theorem nodup_map_on {f : α → β} {l : list α} (H : ∀x∈l, ∀y∈l, f x = f y → x = y)
id                                       └──┘                         
src                                        └──┘                                  
typ                                      └──┘                         
4146    (d : nodup l) : nodup (map f l) :=
id          └───┘     └───┘  └─┘  
src         └───┘      └───┘  └─┘
typ         └───┘     └───┘  └─┘  
doc         └───┘      └───┘
4147  pairwise_map_of_pairwise _ (by exact λ a b ⟨ma, mb, n⟩ e, n (H a ma b mb e)) (pairwise.and_mem.1 d)
id   └──────────────────────┘                    └┘  └┘                          └──────────────┘  
src  └──────────────────────┘       └────┘ └────┘  └┘  └┘ └───┘             └──────────────┘
typ  └──────────────────────┘       └────┘ └────┘└┘└┘└┘└┘└───┘            └──────────────┘  
doc                                 └────┘ └────┘  └┘  └┘ └───┘          
txt                                 └────┘ └────┘  └┘  └┘ └───┘          
par                                 └────┘ └────┘  └┘  └┘ └───┘          
pid                                       └────┘  └┘  └┘ └───┘          
st                                 └───────────────────────────────────────────┘
4148  
4149  theorem nodup_map {f : α → β} {l : list α} (hf : injective f) : nodup l → nodup (map f l) :=
id                                    └──┘         └───────┘     └───┘    └───┘  └─┘  
src                                     └──┘          └───────┘      └───┘     └───┘  └─┘
typ                                   └──┘         └───────┘     └───┘    └───┘  └─┘  
doc                                                                  └───┘     └───┘
4150  nodup_map_on (assume x _ y _ h, hf h)
id   └──────────┘               └┘ 
src  └──────────┘
typ  └──────────┘               └┘ 
4151  
4152  theorem nodup_map_iff {f : α → β} {l : list α} (hf : injective f) : nodup (map f l) ↔ nodup l :=
id                                        └──┘         └───────┘     └───┘  └─┘     └───┘ 
src                                         └──┘          └───────┘      └───┘  └─┘       └───┘
typ                                       └──┘         └───────┘     └───┘  └─┘     └───┘ 
doc                                                                      └───┘             └───┘
4153  ⟨nodup_of_nodup_map _, nodup_map hf⟩
id    └────────────────┘    └───────┘ └┘
src   └────────────────┘    └───────┘
typ   └────────────────┘    └───────┘ └┘
4154  
4155  @[simp] theorem nodup_attach {l : list α} : nodup (attach l) ↔ nodup l :=
id                                     └──┘     └───┘  └────┘    └───┘ 
src                                    └──┘      └───┘  └────┘     └───┘
typ                                    └──┘     └───┘  └────┘    └───┘ 
doc    └──┘                                      └───┘  └────┘      └───┘
4156  ⟨λ h, attach_map_val l ▸ nodup_map (λ a b, subtype.eq) h,
id        └────────────┘   └───────┘       └────────┘  
src        └────────────┘    └───────┘         └────────┘
typ       └────────────┘   └───────┘       └────────┘  
4157   λ h, nodup_of_nodup_map subtype.val ((attach_map_val l).symm ▸ h)⟩
id        └────────────────┘ └─────────┘   └────────────┘  └──┘   
src        └────────────────┘ └─────────┘   └────────────┘   └──┘  
typ       └────────────────┘ └─────────┘   └────────────┘  └──┘   
4158  
4159  theorem nodup_pmap {p : α → Prop} {f : Π a, p a → β} {l : list α} {H}
id                                                        └──┘ 
src                                                            └──┘
typ                                                       └──┘ 
4160    (hf : ∀ a ha b hb, f a ha = f b hb → a = b) (h : nodup l) : nodup (pmap f l H) :=
id              └┘  └┘    └┘    └┘            └───┘     └───┘  └──┘   
src                                                   └───┘      └───┘  └──┘
typ             └┘  └┘    └┘    └┘            └───┘     └───┘  └──┘   
doc                                                     └───┘      └───┘  └──┘
4161  by rw [pmap_eq_map_attach]; exact nodup_map
id          └────────────────┘         └───────┘
src     └──┘└────────────────┘  └────┘└───────┘
typ     └──┘└────────────────┘  └────┘└───────┘
doc     └──┘                    └────┘         
txt     └──┘                    └────┘         
par     └──┘                    └────┘         
pid       └┘                                  
st     └─────────────────────┘└─────────────────
4162    (λ ⟨a, ha⟩ ⟨b, hb⟩ h, by congr; exact hf a (H _ ha) b (H _ hb) h)
id                                           └┘       └┘       └┘  
src  ─┘  └┘ └┘  └─┘ └┘  └───┘  └───┘└──────┘     └─┘  └┘   └─┘  └┘ └─
typ  ─┘  └┘ └┘  └─┘ └┘  └───┘  └───┘└──────┘└┘  └─┘└┘└┘ └─┘└┘└┘└─
doc  ─┘  └┘ └┘  └─┘ └┘  └───┘       └──────┘     └─┘  └┘   └─┘  └┘ └─
txt  ─┘  └┘ └┘  └─┘ └┘  └───┘  └───┘└──────┘     └─┘  └┘   └─┘  └┘ └─
par  ─┘  └┘ └┘  └─┘ └┘  └───┘  └───┘└──────┘     └─┘  └┘   └─┘  └┘ └─
pid  ─┘  └┘ └┘  └─┘ └┘  └───┘  └────────────┘     └─┘  └┘   └─┘  └┘ └─
st   ─────────────────────────┘└──────────────────────────────────────┘└─
4163    (nodup_attach.2 h)
id      └──────────┘   
src  ─┘ └──────────┘└─┘ └─
typ  ─┘ └──────────┘└─┘└─
doc  ─┘             └─┘ └─
txt  ─┘             └─┘ └─
par  ─┘             └─┘ └─
pid  ─┘             └─┘ 
st   ─────────────────────
4164  
src  
typ  
doc  
txt  
par  
pid  
st   
4165  theorem nodup_filter (p : α → Prop) [decidable_pred p] {l} : nodup l → nodup (filter p l) :=
id                                       └────────────┘         └───┘    └───┘  └────┘  
src                                       └────────────┘          └───┘     └───┘  └────┘
typ                                      └────────────┘         └───┘    └───┘  └────┘  
doc                                                               └───┘     └───┘
4166  pairwise_filter_of_pairwise p
id   └─────────────────────────┘ 
src  └─────────────────────────┘
typ  └─────────────────────────┘ 
4167  
4168  @[simp] theorem nodup_reverse {l : list α} : nodup (reverse l) ↔ nodup l :=
id                                      └──┘     └───┘  └─────┘    └───┘ 
src                                     └──┘      └───┘  └─────┘     └───┘
typ                                     └──┘     └───┘  └─────┘    └───┘ 
doc    └──┘                                       └───┘               └───┘
4169  pairwise_reverse.trans $ by simp only [nodup, ne.def, eq_comm]
id   └──────────────┘└────┘                 └───┘  └────┘  └─────┘
src  └──────────────┘└────┘      └─────────┘└───┘└┘└────┘└┘└─────┘└─
typ  └──────────────┘└────┘      └─────────┘└───┘└┘└────┘└┘└─────┘└─
doc                              └─────────┘└───┘└┘      └┘       └─
txt                              └─────────┘     └┘      └┘       └─
par                              └─────────┘     └┘      └┘       └─
pid                                  └──┘└┘     └┘      └┘       
st                              └───────────────────────────────────
4170  
src  
typ  
doc  
txt  
par  
pid  
st   
4171  theorem nodup_erase_eq_filter [decidable_eq α] (a : α) {l} (d : nodup l) : l.erase a = filter (≠ a) l :=
id                                  └──────────┘                   └───┘     └────┘   └────┘     
src                                 └──────────┘                     └───┘       └────┘    └────┘ 
typ                                 └──────────┘                   └───┘     └────┘   └────┘     
doc                                                                  └───┘
4172  begin
st   └─────
4173    induction d with b l m d IH, {refl},
id               
src    └────────┘ └──────────────┘   └──┘
typ    └────────┘└──────────────┘   └──┘
doc    └────────┘ └──────────────┘   └──┘
txt    └────────┘ └──────────────┘   └──┘
par    └────────┘ └──────────────┘   └──┘
pid              └─────────────┘
st   ────────────────────────────┘└─────┘└┘
4174    by_cases b = a,
id                
src    └───────┘ 
typ    └───────┘
doc    └───────┘  
txt    └───────┘  
par    └───────┘  
pid              
st   ───────────────┘└─
4175    { subst h, rw [erase_cons_head, filter_cons_of_neg],
id                   └─────────────┘  └────────────────┘
src      └────┘   └──┘└─────────────┘└┘└────────────────┘
typ      └────┘  └──┘└─────────────┘└┘└────────────────┘
doc      └────┘   └──┘               └┘                  
txt      └────┘   └──┘               └┘                  
par      └────┘   └──┘               └┘                  
pid                └┘               └┘                  
st   ───┘└─────┘└───────────────────┘└──────────────────┘└──
4176      symmetry, rw filter_eq_self, simpa only [ne.def, eq_comm] using m, exact not_not_intro rfl },
id                    └────────────┘              └────┘  └─────┘                └───────────┘ └─┘
src      └──────┘  └─┘└────────────┘  └──────────┘└────┘└┘└─────┘└──────┘   └────┘└───────────┘└─┘
typ      └──────┘  └─┘└────────────┘  └──────────┘└────┘└┘└─────┘└──────┘  └────┘└───────────┘└─┘
doc      └──────┘  └─┘                └──────────┘      └┘       └──────┘   └────┘                
txt      └──────┘  └─┘                └──────────┘      └┘       └──────┘   └────┘                
par      └──────┘  └─┘                └──────────┘      └┘       └──────┘   └────┘                
pid                                       └──┘└┘      └┘       └────┘                        
st   ───────────┘└─────────────────┘└────────────────────────────────────┘└────────────────────────┘└┘
4177    { rw [erase_cons_tail _ h, filter_cons_of_pos, IH], exact h }
id           └─────────────┘     └────────────────┘  └┘         
src      └──┘└─────────────┘└─┘ └┘└────────────────┘└┘    └────┘ 
typ      └──┘└─────────────┘└─┘└┘└────────────────┘└┘└┘  └────┘
doc      └──┘               └─┘ └┘                  └┘    └────┘ 
txt      └──┘               └─┘ └┘                  └┘    └────┘ 
par      └──┘               └─┘ └┘                  └┘    └────┘ 
pid        └┘               └─┘ └┘                  └┘          
st   ──────────────────────────┘└──────────────────┘└──┘└─────────┘└─
4178  end
st   ──┘
4179  
4180  theorem nodup_erase_of_nodup [decidable_eq α] (a : α) {l} : nodup l → nodup (l.erase a) :=
id                                 └──────────┘                └───┘    └───┘  └────┘ 
src                                └──────────┘                  └───┘     └───┘   └────┘
typ                                └──────────┘                └───┘    └───┘  └────┘ 
doc                                                              └───┘     └───┘
4181  nodup_of_sublist (erase_sublist _ _)
id   └──────────────┘  └───────────┘
src  └──────────────┘  └───────────┘
typ  └──────────────┘  └───────────┘
4182  
4183  theorem nodup_diff [decidable_eq α] : ∀ {l₁ l₂ : list α} (h : l₁.nodup), (l₁.diff l₂).nodup
id                       └──────────┘               └──┘        └┘└────┘    └┘└───┘ └┘ └───┘
src                      └──────────┘                 └──┘           └────┘      └───┘    └───┘
typ                      └──────────┘               └──┘        └┘└────┘    └┘└───┘ └┘ └───┘
doc                                                                  └────┘               └───┘
4184  | l₁ []      h := h
id        └┘      
src       └┘
typ       └┘      
4185  | l₁ (a::l₂) h := by rw diff_cons; exact nodup_diff (nodup_erase_of_nodup _ h)
id          └┘               └───────┘        └────────┘  └──────────────────┘   
src         └┘            └─┘└───────┘  └────┘           └──────────────────┘└─┘ └─
typ         └┘            └─┘└───────┘  └────┘└────────┘ └──────────────────┘└─┘└─
doc                       └─┘           └────┘                               └─┘ └─
txt                       └─┘           └────┘                               └─┘ └─
par                       └─┘           └────┘                               └─┘ └─
pid                                                                        └─┘ 
st                       └──────────────────────────────────────────────────────────
4186  
src  
typ  
doc  
txt  
par  
pid  
st   
4187  theorem mem_erase_iff_of_nodup [decidable_eq α] {a b : α} {l} (d : nodup l) :
id                                   └──────────┘                     └───┘ 
src                                  └──────────┘                       └───┘
typ                                  └──────────┘                     └───┘ 
doc                                                                     └───┘
4188    a ∈ l.erase b ↔ a ≠ b ∧ a ∈ l :=
id       └────┘         
src        └────┘            
typ      └────┘         
4189  by rw nodup_erase_eq_filter b d; simp only [mem_filter, and_comm]
id         └───────────────────┘               └────────┘  └──────┘
src     └─┘└───────────────────┘    └─────────┘└────────┘└┘└──────┘└─
typ     └─┘└───────────────────┘  └─────────┘└────────┘└┘└──────┘└─
doc     └─┘                         └─────────┘          └┘        └─
txt     └─┘                         └─────────┘          └┘        └─
par     └─┘                         └─────────┘          └┘        └─
pid                                    └──┘└┘          └┘        
st     └───────────────────────────────────────────────────────────────
4190  
src  
typ  
doc  
txt  
par  
pid  
st   
4191  theorem mem_erase_of_nodup [decidable_eq α] {a : α} {l} (h : nodup l) : a ∉ l.erase a :=
id                               └──────────┘                   └───┘       └────┘ 
src                              └──────────┘                     └───┘          └────┘
typ                              └──────────┘                   └───┘       └────┘ 
doc                                                               └───┘
4192  λ H, ((mem_erase_iff_of_nodup h).1 H).1 rfl
id         └────────────────────┘       └─┘
src         └────────────────────┘         └─┘
typ        └────────────────────┘       └─┘
4193  
4194  theorem nodup_join {L : list (list α)} : nodup (join L) ↔ (∀ l ∈ L, nodup l) ∧ pairwise disjoint L :=
id                           └──┘  └──┘      └───┘  └──┘            └───┘    └──────┘ └──────┘ 
src                          └──┘  └──┘       └───┘  └──┘               └───┘     └──────┘ └──────┘
typ                          └──┘  └──┘      └───┘  └──┘            └───┘    └──────┘ └──────┘ 
doc                                           └───┘                      └───┘      └──────┘ └──────┘
4195  by simp only [nodup, pairwise_join, disjoint_left.symm, forall_mem_ne]
id                 └───┘  └───────────┘                      └───────────┘
src     └─────────┘└───┘└┘└───────────┘└┘                  └┘└───────────┘└─
typ     └─────────┘└───┘└┘└───────────┘└┘└────────────────┘└┘└───────────┘└─
doc     └─────────┘└───┘└┘             └┘                  └┘             └─
txt     └─────────┘     └┘             └┘                  └┘             └─
par     └─────────┘     └┘             └┘                  └┘             └─
pid         └──┘└┘     └┘             └┘                  └┘             
st     └────────────────────────────────────────────────────────────────────
4196  
src  
typ  
doc  
txt  
par  
pid  
st   
4197  theorem nodup_bind {l₁ : list α} {f : α → list β} : nodup (l₁.bind f) ↔
id                            └──┘           └──┘     └───┘  └┘└───┘   
src                           └──┘             └──┘      └───┘    └───┘    
typ                           └──┘           └──┘     └───┘  └┘└───┘   
doc                                                      └───┘
4198    (∀ x ∈ l₁, nodup (f x)) ∧ pairwise (λ (a b : α), disjoint (f a) (f b)) l₁ :=
id           └┘  └───┘       └──────┘              └──────┘          └┘
src               └───┘         └──────┘               └──────┘
typ          └┘  └───┘       └──────┘              └──────┘          └┘
doc               └───┘          └──────┘               └──────┘
4199  by simp only [list.bind, nodup_join, pairwise_map, and_comm, and.left_comm, mem_map, exists_imp_distrib, and_imp];
id                 └───────┘  └────────┘  └──────────┘  └──────┘  └───────────┘  └─────┘  └────────────────┘  └─────┘
src     └─────────┘└───────┘└┘└────────┘└┘└──────────┘└┘└──────┘└┘└───────────┘└┘└─────┘└┘└────────────────┘└┘└─────┘
typ     └─────────┘└───────┘└┘└────────┘└┘└──────────┘└┘└──────┘└┘└───────────┘└┘└─────┘└┘└────────────────┘└┘└─────┘
doc     └─────────┘         └┘          └┘            └┘        └┘             └┘       └┘                  └┘       
txt     └─────────┘         └┘          └┘            └┘        └┘             └┘       └┘                  └┘       
par     └─────────┘         └┘          └┘            └┘        └┘             └┘       └┘                  └┘       
pid         └──┘└┘         └┘          └┘            └┘        └┘             └┘       └┘                  └┘       
st     └────────────────────────────────────────────────────────────────────────────────────────────────────────────────
4200     rw [show (∀ (l : list β) (x : α), f x = l → x ∈ l₁ → nodup l) ↔
id                       └──┘                                      
src     └──┘      └────┘└──┘ └─────┘                └┘ 
typ     └──┘      └────┘└──┘└─────┘                └┘
doc     └──┘      └────┘     └─────┘                  └┘ 
txt     └──┘      └────┘     └─────┘                  └┘ 
par     └──┘      └────┘     └─────┘                  └┘ 
pid       └┘      └────┘     └─────┘                  └┘ 
st   ──────┘└───────────────────────────────────────────────────────────
4201              (∀ (x : α), x ∈ l₁ → nodup (f x)),
id                             └┘   └───┘  
src  ───────────┘  └────┘       └───┘   └───
typ  ───────────┘  └────┘  └┘ └───┘  └───
doc  ───────────┘  └────┘       └───┘   └───
txt  ───────────┘  └────┘               └───
par  ───────────┘  └────┘               └───
pid  ───────────┘  └────┘               └───
st   ───────────────────────────────────────────────
4202         from forall_swap.trans $ forall_congr $ λ_, forall_eq']
id               └───────────────┘   └──────────┘       └────────┘
src  ───────────┘└───────────────┘ └──────────┘  └─┘└────────┘└─
typ  ───────────┘└───────────────┘ └──────────┘  └─┘└────────┘└─
doc  ───────────┘                                └─┘          └─
txt  ───────────┘                                └─┘          └─
par  ───────────┘                                └─┘          └─
pid  ───────────┘                                └─┘          
st   ────────────────────────────────────────────────────────────┘
4203  
src  
typ  
doc  
txt  
par  
pid  
st   
4204  theorem nodup_product {l₁ : list α} {l₂ : list β} (d₁ : nodup l₁) (d₂ : nodup l₂) :
id                               └──┘         └──┘         └───┘ └┘        └───┘ └┘
src                              └──┘          └──┘          └───┘           └───┘
typ                              └──┘         └──┘         └───┘ └┘        └───┘ └┘
doc                                                          └───┘           └───┘
4205    nodup (product l₁ l₂) :=
id     └───┘  └─────┘ └┘ └┘
src    └───┘  └─────┘
typ    └───┘  └─────┘ └┘ └┘
doc    └───┘  └─────┘
4206   nodup_bind.2
id    └────────┘
src   └────────┘
typ   └────────┘
4207    ⟨λ a ma, nodup_map (injective_of_left_inverse (λ b, (rfl : (a,b).2 = b))) d₂,
id         └┘  └───────┘  └───────────────────────┘       └─┘            └┘
src             └───────┘  └───────────────────────┘        └─┘         
typ        └┘  └───────┘  └───────────────────────┘       └─┘            └┘
4208    d₁.imp $ λ a₁ a₂ n x h₁ h₂, begin
id     └┘└──┘     └┘ └┘   └┘ └┘
src      └──┘
typ    └┘└──┘     └┘ └┘   └┘ └┘
st                                 └─────
4209      rcases mem_map.1 h₁ with ⟨b₁, mb₁, rfl⟩,
id              └─────┘   └┘
src      └─────┘└─────┘└─┘  └──────────────────┘
typ      └─────┘└─────┘└─┘└┘└──────────────────┘
doc      └─────┘       └─┘  └──────────────────┘
txt      └─────┘       └─┘  └──────────────────┘
par      └─────┘       └─┘  └──────────────────┘
pid                   └─┘  └──────────────────┘
st   ──────────────────────────────────────────┘└─
4210      rcases mem_map.1 h₂ with ⟨b₂, mb₂, ⟨⟩⟩,
id              └─────┘   └┘
src      └─────┘└─────┘└─┘  └─────────────────┘
typ      └─────┘└─────┘└─┘└┘└─────────────────┘
doc      └─────┘       └─┘  └─────────────────┘
txt      └─────┘       └─┘  └─────────────────┘
par      └─────┘       └─┘  └─────────────────┘
pid                   └─┘  └─────────────────┘
st   ─────────────────────────────────────────┘└─
4211      exact n rfl
id              └─┘
src      └────┘ └─┘
typ      └────┘└─┘
doc      └────┘    
txt      └────┘    
par      └────┘    
pid               
st   ────────────────
4212    end⟩
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
4213  
4214  theorem nodup_sigma {σ : α → Type*} {l₁ : list α} {l₂ : Π a, list (σ a)}
id                                            └──┘             └──┘   
src                                            └──┘               └──┘
typ                                           └──┘             └──┘   
4215    (d₁ : nodup l₁) (d₂ : ∀ a, nodup (l₂ a)) : nodup (l₁.sigma l₂) :=
id           └───┘ └┘            └───┘  └┘      └───┘  └┘└────┘ └┘
src          └───┘                └───┘           └───┘    └────┘
typ          └───┘ └┘            └───┘  └┘      └───┘  └┘└────┘ └┘
doc          └───┘                └───┘           └───┘    └────┘
4216   nodup_bind.2
id    └────────┘
src   └────────┘
typ   └────────┘
4217    ⟨λ a ma, nodup_map (λ b b' h, by injection h with _ h; exact eq_of_heq h) (d₂ a),
id         └┘  └───────┘     └┘                                 └───────┘    └┘ 
src             └───────┘               └────────┘ └───────┘  └────┘└───────┘
typ        └┘  └───────┘     └┘      └────────┘└───────┘  └────┘└───────┘   └┘ 
doc                                     └────────┘ └───────┘  └────┘         
txt                                     └────────┘ └───────┘  └────┘         
par                                     └────────┘ └───────┘  └────┘         
pid                                               └───────┘                
st                                     └──────────────────────────────────────┘
4218    d₁.imp $ λ a₁ a₂ n x h₁ h₂, begin
id     └┘└──┘     └┘ └┘   └┘ └┘
src      └──┘
typ    └┘└──┘     └┘ └┘   └┘ └┘
st                                 └─────
4219      rcases mem_map.1 h₁ with ⟨b₁, mb₁, rfl⟩,
id              └─────┘   └┘
src      └─────┘└─────┘└─┘  └──────────────────┘
typ      └─────┘└─────┘└─┘└┘└──────────────────┘
doc      └─────┘       └─┘  └──────────────────┘
txt      └─────┘       └─┘  └──────────────────┘
par      └─────┘       └─┘  └──────────────────┘
pid                   └─┘  └──────────────────┘
st   ──────────────────────────────────────────┘└─
4220      rcases mem_map.1 h₂ with ⟨b₂, mb₂, ⟨⟩⟩,
id              └─────┘   └┘
src      └─────┘└─────┘└─┘  └─────────────────┘
typ      └─────┘└─────┘└─┘└┘└─────────────────┘
doc      └─────┘       └─┘  └─────────────────┘
txt      └─────┘       └─┘  └─────────────────┘
par      └─────┘       └─┘  └─────────────────┘
pid                   └─┘  └─────────────────┘
st   ─────────────────────────────────────────┘└─
4221      exact n rfl
id              └─┘
src      └────┘ └─┘
typ      └────┘└─┘
doc      └────┘    
txt      └────┘    
par      └────┘    
pid               
st   ────────────────
4222    end⟩
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
4223  
4224  theorem nodup_filter_map {f : α → option β} {l : list α}
id                                    └────┘        └──┘ 
src                                    └────┘         └──┘
typ                                   └────┘        └──┘ 
4225    (H : ∀ (a a' : α) (b : β), b ∈ f a → b ∈ f a' → a = a') :
id                                       └┘     └┘
src                                                    
typ                                      └┘     └┘
4226    nodup l → nodup (filter_map f l) :=
id     └───┘    └───┘  └────────┘  
src    └───┘     └───┘  └────────┘
typ    └───┘    └───┘  └────────┘  
doc    └───┘     └───┘
4227  pairwise_filter_map_of_pairwise f $ λ a a' n b bm b' bm' e, n $ H a a' b' (e ▸ bm) bm'
id   └─────────────────────────────┘       └┘   └┘ └┘ └─┘        └┘ └┘    └┘  └─┘
src  └─────────────────────────────┘                                              
typ  └─────────────────────────────┘       └┘   └┘ └┘ └─┘        └┘ └┘    └┘  └─┘
4228  
4229  theorem nodup_concat {a : α} {l : list α} (h : a ∉ l) (h' : nodup l) : nodup (concat l a) :=
id                                    └──┘                  └───┘     └───┘  └────┘  
src                                    └──┘                     └───┘      └───┘  └────┘
typ                                   └──┘                  └───┘     └───┘  └────┘  
doc                                                              └───┘      └───┘  └────┘
4230  by rw concat_eq_append; exact nodup_append_of_nodup h' (nodup_singleton _) (disjoint_singleton.2 h)
id         └──────────────┘        └───────────────────┘ └┘  └─────────────┘     └────────────────┘   
src     └─┘└──────────────┘  └────┘└───────────────────┘   └─────────────┘└──┘ └────────────────┘└─┘ └─
typ     └─┘└──────────────┘  └────┘└───────────────────┘└┘ └─────────────┘└──┘ └────────────────┘└─┘└─
doc     └─┘                  └────┘                                       └──┘                   └─┘ └─
txt     └─┘                  └────┘                                       └──┘                   └─┘ └─
par     └─┘                  └────┘                                       └──┘                   └─┘ └─
pid                                                                     └──┘                   └─┘ 
st     └─────────────────────────────────────────────────────────────────────────────────────────────────
4231  
src  
typ  
doc  
txt  
par  
pid  
st   
4232  theorem nodup_insert [decidable_eq α] {a : α} {l : list α} (h : nodup l) : nodup (insert a l) :=
id                         └──────────┘               └──┘        └───┘     └───┘  └────┘  
src                        └──────────┘                 └──┘         └───┘      └───┘  └────┘
typ                        └──────────┘               └──┘        └───┘     └───┘  └────┘  
doc                                                                  └───┘      └───┘
4233  if h' : a ∈ l then by rw [insert_of_mem h']; exact h
id   └┘                     └───────────┘ └┘         
src  └┘                   └──┘└───────────┘    └────┘ 
typ  └┘                 └──┘└───────────┘└┘  └────┘
doc                        └──┘                 └────┘ 
txt                        └──┘                 └────┘ 
par                        └──┘                 └────┘ 
pid                          └┘                       
st                        └───────────────────┘└────────┘
4234  else by rw [insert_of_not_mem h', nodup_cons]; split; assumption
id               └───────────────┘ └┘  └────────┘
src          └──┘└───────────────┘  └┘└────────┘  └───┘  └──────────
typ          └──┘└───────────────┘└┘└┘└────────┘  └───┘  └──────────
doc          └──┘                   └┘            └───┘  └──────────
txt          └──┘                   └┘            └───┘  └──────────
par          └──┘                   └┘            └───┘  └──────────
pid            └┘                   └┘                             
st          └───────────────────────┘└──────────┘└───────────────────
4235  
src  
typ  
doc  
txt  
par  
pid  
st   
4236  theorem nodup_union [decidable_eq α] (l₁ : list α) {l₂ : list α} (h : nodup l₂) :
id                        └──────────┘         └──┘         └──┘        └───┘ └┘
src                       └──────────┘          └──┘          └──┘         └───┘
typ                       └──────────┘         └──┘         └──┘        └───┘ └┘
doc                                                                        └───┘
4237    nodup (l₁ ∪ l₂) :=
id     └───┘  └┘  └┘
src    └───┘     
typ    └───┘  └┘  └┘
doc    └───┘
4238  begin
st   └─────
4239    induction l₁ with a l₁ ih generalizing l₂,
id               └┘
src    └────────┘  └───────────────────────────┘
typ    └────────┘└┘└───────────────────────────┘
doc    └────────┘  └───────────────────────────┘
txt    └────────┘  └───────────────────────────┘
par    └────────┘  └───────────────────────────┘
pid               └──────────┘└──────────────┘
st   ──────────────────────────────────────────┘└─
4240    { exact h },
id             
src      └────┘ 
typ      └────┘
doc      └────┘ 
txt      └────┘ 
par      └────┘ 
pid            
st   ───┘└──────┘└┘
4241    apply nodup_insert,
id           └──────────┘
src    └────┘└──────────┘
typ    └────┘└──────────┘
doc    └────┘
txt    └────┘
par    └────┘
pid         
st   ───────────────────┘└─
4242    exact ih h
id           └┘ 
src    └────┘   
typ    └────┘└┘
doc    └────┘   
txt    └────┘   
par    └────┘   
pid            
st   ────────────┘
4243  end
st   └─┘
4244  
4245  theorem nodup_inter_of_nodup [decidable_eq α] {l₁ : list α} (l₂) : nodup l₁ → nodup (l₁ ∩ l₂) :=
id                                 └──────────┘         └──┘          └───┘ └┘   └───┘  └┘  └┘
src                                └──────────┘          └──┘           └───┘      └───┘     
typ                                └──────────┘         └──┘          └───┘ └┘   └───┘  └┘  └┘
doc                                                                     └───┘      └───┘
4246  nodup_filter _
id   └──────────┘
src  └──────────┘
typ  └──────────┘
4247  
4248  @[simp] theorem nodup_sublists {l : list α} : nodup (sublists l) ↔ nodup l :=
id                                       └──┘     └───┘  └──────┘    └───┘ 
src                                      └──┘      └───┘  └──────┘     └───┘
typ                                      └──┘     └───┘  └──────┘    └───┘ 
doc    └──┘                                        └───┘  └──────┘      └───┘
4249  ⟨λ h, nodup_of_nodup_map _ (nodup_of_sublist (map_ret_sublist_sublists _) h),
id        └────────────────┘    └──────────────┘  └──────────────────────┘    
src        └────────────────┘    └──────────────┘  └──────────────────────┘
typ       └────────────────┘    └──────────────┘  └──────────────────────┘    
4250   λ h, (pairwise_sublists h).imp (λ _ _ h, mt reverse_inj.2 h.to_ne)⟩
id         └───────────────┘  └─┘         └┘ └─────────┘  └────┘
src         └───────────────┘   └─┘            └┘ └─────────┘   └────┘
typ        └───────────────┘  └─┘         └┘ └─────────┘  └────┘
4251  
4252  @[simp] theorem nodup_sublists' {l : list α} : nodup (sublists' l) ↔ nodup l :=
id                                        └──┘     └───┘  └───────┘    └───┘ 
src                                       └──┘      └───┘  └───────┘     └───┘
typ                                       └──┘     └───┘  └───────┘    └───┘ 
doc    └──┘                                         └───┘  └───────┘      └───┘
4253  by rw [sublists'_eq_sublists, nodup_map_iff reverse_injective,
id          └───────────────────┘  └───────────┘ └───────────────┘
src     └──┘└───────────────────┘└┘└───────────┘└───────────────┘└─
typ     └──┘└───────────────────┘└┘└───────────┘└───────────────┘└─
doc     └──┘                     └┘                              └─
txt     └──┘                     └┘                              └─
par     └──┘                     └┘                              └─
pid       └┘                     └┘                              └─
st     └────────────────────────┘└───────────────────────────────┘└─
4254         nodup_sublists, nodup_reverse]
id          └────────────┘  └───────────┘
src  ──────┘└────────────┘└┘└───────────┘└─
typ  ──────┘└────────────┘└┘└───────────┘└─
doc  ──────┘              └┘             └─
txt  ──────┘              └┘             └─
par  ──────┘              └┘             └─
pid  ──────┘              └┘             
st   ────────────────────┘└─────────────┘
4255  
src  
typ  
doc  
txt  
par  
pid  
st   
4256  lemma nodup_sublists_len {α : Type*} (n) {l : list α}
id                                                 └──┘ 
src                                                └──┘
typ                                                └──┘ 
4257    (nd : nodup l) : (sublists_len n l).nodup :=
id           └───┘      └──────────┘   └───┘
src          └───┘       └──────────┘     └───┘
typ          └───┘      └──────────┘   └───┘
doc          └───┘                        └───┘
4258  nodup_of_sublist (sublists_len_sublist_sublists' _ _) (nodup_sublists'.2 nd)
id   └──────────────┘  └────────────────────────────┘       └─────────────┘  └┘
src  └──────────────┘  └────────────────────────────┘       └─────────────┘
typ  └──────────────┘  └────────────────────────────┘       └─────────────┘  └┘
4259  
4260  lemma diff_eq_filter_of_nodup [decidable_eq α] :
id                                  └──────────┘ 
src                                 └──────────┘
typ                                 └──────────┘ 
4261    ∀ {l₁ l₂ : list α} (hl₁ : l₁.nodup), l₁.diff l₂ = l₁.filter (∉ l₂)
id               └──┘          └┘└────┘   └┘└───┘ └┘  └┘└─────┘   └┘
src               └──┘             └────┘     └───┘       └─────┘ 
typ              └──┘          └┘└────┘   └┘└───┘ └┘  └┘└─────┘   └┘
doc                                └────┘
4262  | l₁ []      hl₁ := by simp
id        └┘
src       └┘                └───┘
typ       └┘                └───┘
doc                         └───┘
txt                         └───┘
par                         └───┘
pid                             
st                         └────┘
4263  | l₁ (a::l₂) hl₁ :=
id          └┘
src         └┘
typ         └┘
4264  begin
st   └─────
4265    rw [diff_cons, diff_eq_filter_of_nodup (nodup_erase_of_nodup _ hl₁),
id         └───────┘  └─────────────────────┘  └──────────────────┘   └─┘
src    └──┘└───────┘└┘                        └──────────────────┘└─┘   └──
typ    └──┘└───────┘└┘└─────────────────────┘ └──────────────────┘└─┘└─┘└──
doc    └──┘         └┘                                            └─┘   └──
txt    └──┘         └┘                                            └─┘   └──
par    └──┘         └┘                                            └─┘   └──
pid      └┘         └┘                                            └─┘   └──
st   ──────────────┘└────────────────────────────────────────────────────┘└─
4266      nodup_erase_eq_filter _ hl₁, filter_filter],
id       └───────────────────┘   └─┘  └───────────┘
src  ───┘└───────────────────┘└─┘   └┘└───────────┘
typ  ───┘└───────────────────┘└─┘└─┘└┘└───────────┘
doc  ───┘                     └─┘   └┘             
txt  ───┘                     └─┘   └┘             
par  ───┘                     └─┘   └┘             
pid  ───┘                     └─┘   └┘             
st   ──────────────────────────────┘└─────────────┘└──
4267    simp only [mem_cons_iff, not_or_distrib, and.comm],
id                └──────────┘  └────────────┘  └──────┘
src    └─────────┘└──────────┘└┘└────────────┘└┘└──────┘
typ    └─────────┘└──────────┘└┘└────────────┘└┘└──────┘
doc    └─────────┘            └┘              └┘        
txt    └─────────┘            └┘              └┘        
par    └─────────┘            └┘              └┘        
pid        └──┘└┘            └┘              └┘        
st   ───────────────────────────────────────────────────┘└─
4268    congr
src    └────┘
typ    └────┘
txt    └────┘
par    └────┘
pid         
st   ───────┘
4269  end
st   └─┘
4270  
4271  lemma mem_diff_iff_of_nodup [decidable_eq α] {l₁ l₂ : list α} (hl₁ : l₁.nodup) {a : α} :
id                                └──────────┘            └──┘          └┘└────┘       
src                               └──────────┘             └──┘             └────┘
typ                               └──────────┘            └──┘          └┘└────┘       
doc                                                                         └────┘
4272    a ∈ l₁.diff l₂ ↔ a ∈ l₁ ∧ a ∉ l₂ :=
id       └┘└───┘ └┘    └┘    └┘
src         └───┘              
typ      └┘└───┘ └┘    └┘    └┘
4273  by rw [diff_eq_filter_of_nodup hl₁, mem_filter]
id          └─────────────────────┘ └─┘  └────────┘
src     └──┘└─────────────────────┘   └┘└────────┘└─
typ     └──┘└─────────────────────┘└─┘└┘└────────┘└─
doc     └──┘                          └┘          └─
txt     └──┘                          └┘          └─
par     └──┘                          └┘          └─
pid       └┘                          └┘          
st     └──────────────────────────────┘└──────────┘
4274  
src  
typ  
doc  
txt  
par  
pid  
st   
4275  lemma nodup_update_nth : ∀ {l : list α} {n : ℕ} {a : α} (hl : l.nodup) (ha : a ∉ l),
id                                  └──┘                       └────┘          
src                                  └──┘                          └────┘          
typ                                 └──┘                       └────┘          
doc                                                                 └────┘
4276    (l.update_nth n a).nodup
id      └─────────┘   └───┘
src      └─────────┘     └───┘
typ     └─────────┘   └───┘
doc                      └───┘
4277  | []     n     a hl ha := nodup_nil
id     └┘                      └───────┘
src    └┘                      └───────┘
typ    └┘                      └───────┘
4278  | (b::l) 0     a hl ha := nodup_cons.2 ⟨mt (mem_cons_of_mem _) ha, (nodup_cons.1 hl).2⟩
id       └┘           └┘ └┘    └────────┘   └┘  └─────────────┘         └────────┘     
src      └┘                    └────────┘   └┘  └─────────────┘         └────────┘     
typ      └┘           └┘ └┘    └────────┘   └┘  └─────────────┘         └────────┘     
4279  | (b::l) (n+1) a hl ha := nodup_cons.2
id       └┘          └┘ └┘    └────────┘
src      └┘                   └────────┘
typ      └┘          └┘ └┘    └────────┘
4280    ⟨λ h, (mem_or_eq_of_mem_update_nth h).elim
id           └─────────────────────────┘  └──┘
src           └─────────────────────────┘   └──┘
typ          └─────────────────────────┘  └──┘
4281        (nodup_cons.1 hl).1
id          └────────┘     
src         └────────┘     
typ         └────────┘     
4282        (λ hba, ha (hba ▸ mem_cons_self _ _)),
id            └─┘      └─┘  └───────────┘
src                         └───────────┘
typ           └─┘      └─┘  └───────────┘
4283      nodup_update_nth (nodup_cons.1 hl).2 (mt (mem_cons_of_mem _) ha)⟩
id       └──────────────┘  └────────┘        └┘  └─────────────┘
src                        └────────┘        └┘  └─────────────┘
typ      └──────────────┘  └────────┘        └┘  └─────────────┘
4284  
4285  end nodup
4286  
4287  /- erase duplicates function -/
4288  
4289  section erase_dup
4290  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
4291  
4292  @[simp] theorem erase_dup_nil : erase_dup [] = ([] : list α) := rfl
id                                   └───────┘ └┘   └┘   └──┘      └─┘
src                                  └───────┘ └┘   └┘   └──┘       └─┘
typ                                  └───────┘ └┘   └┘   └──┘      └─┘
doc    └──┘                          └───────┘
4293  
4294  theorem erase_dup_cons_of_mem' {a : α} {l : list α} (h : a ∈ erase_dup l) :
id                                              └──┘          └───────┘ 
src                                              └──┘            └───────┘
typ                                             └──┘          └───────┘ 
doc                                                               └───────┘
4295    erase_dup (a::l) = erase_dup l :=
id     └───────┘  └┘   └───────┘ 
src    └───────┘   └┘    └───────┘
typ    └───────┘  └┘   └───────┘ 
doc    └───────┘          └───────┘
4296  pw_filter_cons_of_neg $ by simpa only [forall_mem_ne] using h
id   └───────────────────┘                  └───────────┘        
src  └───────────────────┘      └──────────┘└───────────┘└──────┘ 
typ  └───────────────────┘      └──────────┘└───────────┘└──────┘
doc                             └──────────┘             └──────┘ 
txt                             └──────────┘             └──────┘ 
par                             └──────────┘             └──────┘ 
pid                                  └──┘└┘             └────┘ 
st                             └───────────────────────────────────
4297  
src  
typ  
doc  
txt  
par  
pid  
st   
4298  theorem erase_dup_cons_of_not_mem' {a : α} {l : list α} (h : a ∉ erase_dup l) :
id                                                  └──┘          └───────┘ 
src                                                  └──┘            └───────┘
typ                                                 └──┘          └───────┘ 
doc                                                                   └───────┘
4299    erase_dup (a::l) = a :: erase_dup l :=
id     └───────┘  └┘    └┘ └───────┘ 
src    └───────┘   └┘      └┘ └───────┘
typ    └───────┘  └┘    └┘ └───────┘ 
doc    └───────┘               └───────┘
4300  pw_filter_cons_of_pos $ by simpa only [forall_mem_ne] using h
id   └───────────────────┘                  └───────────┘        
src  └───────────────────┘      └──────────┘└───────────┘└──────┘ 
typ  └───────────────────┘      └──────────┘└───────────┘└──────┘
doc                             └──────────┘             └──────┘ 
txt                             └──────────┘             └──────┘ 
par                             └──────────┘             └──────┘ 
pid                                  └──┘└┘             └────┘ 
st                             └───────────────────────────────────
4301  
src  
typ  
doc  
txt  
par  
pid  
st   
4302  @[simp] theorem mem_erase_dup {a : α} {l : list α} : a ∈ erase_dup l ↔ a ∈ l :=
id                                             └──┘       └───────┘     
src                                             └──┘         └───────┘      
typ                                            └──┘       └───────┘     
doc    └──┘                                                   └───────┘
4303  by simpa only [erase_dup, forall_mem_ne, not_not] using not_congr (@forall_mem_pw_filter α (≠) _
id                  └───────┘  └───────────┘  └─────┘        └───────┘   └──────────────────┘  
src     └──────────┘└───────┘└┘└───────────┘└┘└─────┘└──────┘└───────┘  └──────────────────┘ └────
typ     └──────────┘└───────┘└┘└───────────┘└┘└─────┘└──────┘└───────┘  └──────────────────┘└────
doc     └──────────┘└───────┘└┘             └┘       └──────┘                                 └────
txt     └──────────┘         └┘             └┘       └──────┘                                 └────
par     └──────────┘         └┘             └┘       └──────┘                                 └────
pid          └──┘└┘         └┘             └┘       └────┘                                 └────
st     └──────────────────────────────────────────────────────────────────────────────────────────────
4304    (λ x y z xz, not_and_distrib.1 $ mt (and.rec eq.trans) xz) a l)
id                  └─────────────┘     └┘  └─────┘ └──────┘       
src  ─┘  └─────────┘└─────────────┘└─┘ └┘ └─────┘└──────┘└┘  └┘  └─
typ  ─┘  └─────────┘└─────────────┘└─┘ └┘ └─────┘└──────┘└┘  └┘└─
doc  ─┘  └─────────┘               └─┘                   └┘  └┘  └─
txt  ─┘  └─────────┘               └─┘                   └┘  └┘  └─
par  ─┘  └─────────┘               └─┘                   └┘  └┘  └─
pid  ─┘  └─────────┘               └─┘                   └┘  └┘  
st   ──────────────────────────────────────────────────────────────────
4305  
src  
typ  
doc  
txt  
par  
pid  
st   
4306  @[simp] theorem erase_dup_cons_of_mem {a : α} {l : list α} (h : a ∈ l) :
id                                                     └──┘          
src                                                     └──┘           
typ                                                    └──┘          
doc    └──┘
4307    erase_dup (a::l) = erase_dup l :=
id     └───────┘  └┘   └───────┘ 
src    └───────┘   └┘    └───────┘
typ    └───────┘  └┘   └───────┘ 
doc    └───────┘          └───────┘
4308  erase_dup_cons_of_mem' $ mem_erase_dup.2 h
id   └────────────────────┘   └───────────┘  
src  └────────────────────┘   └───────────┘
typ  └────────────────────┘   └───────────┘  
4309  
4310  @[simp] theorem erase_dup_cons_of_not_mem {a : α} {l : list α} (h : a ∉ l) :
id                                                         └──┘          
src                                                         └──┘           
typ                                                        └──┘          
doc    └──┘
4311    erase_dup (a::l) = a :: erase_dup l :=
id     └───────┘  └┘    └┘ └───────┘ 
src    └───────┘   └┘      └┘ └───────┘
typ    └───────┘  └┘    └┘ └───────┘ 
doc    └───────┘               └───────┘
4312  erase_dup_cons_of_not_mem' $ mt mem_erase_dup.1 h
id   └────────────────────────┘   └┘ └───────────┘  
src  └────────────────────────┘   └┘ └───────────┘
typ  └────────────────────────┘   └┘ └───────────┘  
4313  
4314  theorem erase_dup_sublist : ∀ (l : list α), erase_dup l <+ l := pw_filter_sublist
id                                      └──┘    └───────┘  └┘     └───────────────┘
src                                     └──┘     └───────┘   └┘      └───────────────┘
typ                                     └──┘    └───────┘  └┘     └───────────────┘
doc                                              └───────┘
4315  
4316  theorem erase_dup_subset : ∀ (l : list α), erase_dup l ⊆ l := pw_filter_subset
id                                     └──┘    └───────┘       └──────────────┘
src                                    └──┘     └───────┘         └──────────────┘
typ                                    └──┘    └───────┘       └──────────────┘
doc                                             └───────┘
4317  
4318  theorem subset_erase_dup (l : list α) : l ⊆ erase_dup l :=
id                                 └──┘       └───────┘ 
src                                └──┘         └───────┘
typ                                └──┘       └───────┘ 
doc                                              └───────┘
4319  λ a, mem_erase_dup.2
id       └───────────┘
src       └───────────┘
typ      └───────────┘
4320  
4321  theorem nodup_erase_dup : ∀ l : list α, nodup (erase_dup l) := pairwise_pw_filter
id                                   └──┘   └───┘  └───────┘      └────────────────┘
src                                  └──┘    └───┘  └───────┘       └────────────────┘
typ                                  └──┘   └───┘  └───────┘      └────────────────┘
doc                                          └───┘  └───────┘
4322  
4323  theorem erase_dup_eq_self {l : list α} : erase_dup l = l ↔ nodup l := pw_filter_eq_self
id                                  └──┘     └───────┘     └───┘     └───────────────┘
src                                 └──┘      └───────┘       └───┘      └───────────────┘
typ                                 └──┘     └───────┘     └───┘     └───────────────┘
doc                                           └───────┘         └───┘
4324  
4325  @[simp] theorem erase_dup_idempotent {l : list α} : erase_dup (erase_dup l) = erase_dup l :=
id                                             └──┘     └───────┘  └───────┘    └───────┘ 
src                                            └──┘      └───────┘  └───────┘     └───────┘
typ                                            └──┘     └───────┘  └───────┘    └───────┘ 
doc    └──┘                                              └───────┘  └───────┘      └───────┘
4326  pw_filter_idempotent
id   └──────────────────┘
src  └──────────────────┘
typ  └──────────────────┘
4327  
4328  theorem erase_dup_append (l₁ l₂ : list α) : erase_dup (l₁ ++ l₂) = l₁ ∪ erase_dup l₂ :=
id                                     └──┘     └───────┘  └┘ └┘ └┘   └┘  └───────┘ └┘
src                                    └──┘      └───────┘     └┘          └───────┘
typ                                    └──┘     └───────┘  └┘ └┘ └┘   └┘  └───────┘ └┘
doc                                              └───────┘                   └───────┘
4329  begin
st   └─────
4330    induction l₁ with a l₁ IH, {refl}, rw [cons_union, ← IH],
id               └┘                           └────────┘    └┘
src    └────────┘  └───────────┘   └──┘   └──┘└────────┘└──┘  
typ    └────────┘└┘└───────────┘   └──┘   └──┘└────────┘└──┘└┘
doc    └────────┘  └───────────┘   └──┘   └──┘          └──┘  
txt    └────────┘  └───────────┘   └──┘   └──┘          └──┘  
par    └────────┘  └───────────┘   └──┘   └──┘          └──┘  
pid               └──────────┘            └┘          └──┘  
st   ──────────────────────────┘└─────┘└┘└─────────────┘└────┘└─
4331    show erase_dup (a :: (l₁ ++ l₂)) = insert a (erase_dup (l₁ ++ l₂)),
id                              └┘       └────┘   └───────┘  └┘    └┘
src    └───┘                └┘  └─┘└────┘  └───────┘       └┘
typ    └───┘                └┘  └─┘└────┘ └───────┘ └┘  └┘└┘
doc    └───┘                    └─┘         └───────┘       └┘
txt    └───┘                    └─┘                         └┘
par    └───┘                    └─┘                         └┘
pid    └───┘                    └─┘                         └┘
st   ───────────────────────────────────────────────────────────────────┘└─
4332    by_cases a ∈ erase_dup (l₁ ++ l₂);
id                └───────┘  └┘    └┘
src    └───────┘ └───────┘       
typ    └───────┘└───────┘ └┘  └┘
doc    └───────┘  └───────┘       
txt    └───────┘                  
par    └───────┘                  
pid                              
st   ─────────────────────────────────────
4333    [ rw [erase_dup_cons_of_mem' h, insert_of_mem h],
id          └────────────────────┘   └───────────┘ 
src     └──┘└────────────────────┘ └┘└───────────┘ 
typ     └──┘└────────────────────┘└┘└───────────┘
doc      └──┘                       └┘              
txt      └──┘                       └┘              
par      └──┘                       └┘              
pid        └┘                       └┘              
st   ───────┘└──────────────────────┘└───────────────┘└─
4334      rw [erase_dup_cons_of_not_mem' h, insert_of_not_mem h]]
id           └────────────────────────┘   └───────────────┘ 
src      └──┘└────────────────────────┘ └┘└───────────────┘ 
typ      └──┘└────────────────────────┘└┘└───────────────┘
doc      └──┘                           └┘                  
txt      └──┘                           └┘                  
par      └──┘                           └┘                  
pid        └┘                           └┘                  
st   ───────┘└──────────────────────────┘└───────────────────┘
4335  end
st   ──┘
4336  
4337  end erase_dup
4338  
4339  /- iota and range(') -/
4340  
4341  @[simp] theorem length_range' : ∀ (s n : ℕ), length (range' s n) = n
id                                              └────┘  └────┘     
src                                              └────┘  └────┘      
typ                                             └────┘  └────┘     
doc    └──┘                                               └────┘
4342  | s 0     := rfl
id                └─┘
src               └─┘
typ               └─┘
4343  | s (n+1) := congr_arg succ (length_range' _ _)
id               └───────┘ └──┘  └───────────┘
src              └───────┘ └──┘
typ              └───────┘ └──┘  └───────────┘
4344  
4345  @[simp] theorem mem_range' {m : ℕ} : ∀ {s n : ℕ}, m ∈ range' s n ↔ s ≤ m ∧ m < s + n
id                                                    └────┘            
src                                                     └────┘                 
typ                                                   └────┘            
doc    └──┘                                                └────┘
4346  | s 0     := (false_iff _).2 $ λ ⟨H1, H2⟩, not_le_of_lt H2 H1
id                 └───────┘         └┘  └┘   └──────────┘
src                └───────┘                   └──────────┘
typ                └───────┘         └┘  └┘   └──────────┘
4347  | s (succ n) :=
id       └──┘ 
src       └──┘
typ      └──┘ 
4348    have m = s → m < s + n + 1,
id                       
src                        
typ                      
4349      from λ e, e ▸ lt_succ_of_le (le_add_right _ _),
id                  └───────────┘  └──────────┘
src                   └───────────┘  └──────────┘
typ                 └───────────┘  └──────────┘
4350    have l : m = s ∨ s + 1 ≤ m ↔ s ≤ m,
id                              
src                              
typ                             
4351      by simpa only [eq_comm] using (@le_iff_eq_or_lt _ _ s m).symm,
id                      └─────┘          └─────────────┘      
src         └──────────┘└─────┘└──────┘  └─────────────┘└───┘  └────┘
typ         └──────────┘└─────┘└──────┘  └─────────────┘└───┘└────┘
doc         └──────────┘       └──────┘                 └───┘  └────┘
txt         └──────────┘       └──────┘                 └───┘  └────┘
par         └──────────┘       └──────┘                 └───┘  └────┘
pid              └──┘└┘       └────┘                 └───┘  └───┘
st         └─────────────────────────────────────────────────────────┘
4352    (mem_cons_iff _ _ _).trans $ by simp only [mem_range',
id      └──────────┘       └───┘
src     └──────────┘       └───┘       └─────────┘          └─
typ     └──────────┘       └───┘       └─────────┘└────────┘└─
doc                                    └─────────┘          └─
txt                                    └─────────┘          └─
par                                    └─────────┘          └─
pid                                        └──┘└┘          └─
st                                    └───────────────────────
4353      or_and_distrib_left, or_iff_right_of_imp this, l, add_right_comm]; refl
id       └─────────────────┘  └─────────────────┘ └──┘    └────────────┘
src  ───┘└─────────────────┘└┘└─────────────────┘    └┘ └┘└────────────┘  └────
typ  ───┘└─────────────────┘└┘└─────────────────┘└──┘└┘└┘└────────────┘  └────
doc  ───┘                   └┘                       └┘ └┘                └────
txt  ───┘                   └┘                       └┘ └┘                └────
par  ───┘                   └┘                       └┘ └┘                └────
pid  ───┘                   └┘                       └┘ └┘                    
st   ────────────────────────────────────────────────────────────────────────────
4354  
src  
typ  
doc  
txt  
par  
pid  
st   
4355  theorem map_add_range' (a) : ∀ s n : ℕ, map ((+) a) (range' s n) = range' (a + s) n
id                                         └─┘        └────┘     └────┘      
src                                         └─┘         └────┘       └────┘    
typ                                        └─┘        └────┘     └────┘      
doc                                                       └────┘        └────┘
4356  | s 0     := rfl
id                └─┘
src               └─┘
typ               └─┘
4357  | s (n+1) := congr_arg (cons _) (map_add_range' (s+1) n)
id             └───────┘  └──┘     └────────────┘   
src              └───────┘  └──┘                      
typ            └───────┘  └──┘     └────────────┘   
4358  
4359  theorem map_sub_range' (a) : ∀ (s n : ℕ) (h : a ≤ s), map (λ x, x - a) (range' s n) = range' (s - a) n
id                                                    └─┘           └────┘     └────┘      
src                                                      └─┘              └────┘       └────┘    
typ                                                   └─┘           └────┘     └────┘      
doc                                                                          └────┘        └────┘
4360  | s 0     _ := rfl
id                  └─┘
src                 └─┘
typ                 └─┘
4361  | s (n+1) h :=
id         
src        
typ        
4362  begin
st   └─────
4363    convert congr_arg (cons (s-a)) (map_sub_range' (s+1) n (nat.le_succ_of_le h)),
id             └───────┘  └──┘       └────────────┘       └───────────────┘ 
src    └──────┘└───────┘ └──┘   └─┘                 └─┘  └───────────────┘ └┘
typ    └──────┘└───────┘ └──┘  └─┘ └────────────┘ └─┘ └───────────────┘└┘
doc    └──────┘                  └─┘                  └─┘                    └┘
txt    └──────┘                  └─┘                  └─┘                    └┘
par    └──────┘                  └─┘                  └─┘                    └┘
pid                             └─┘                  └─┘                    └┘
st   ──────────────────────────────────────────────────────────────────────────────┘└─
4364    rw nat.succ_sub h,
id        └──────────┘ 
src    └─┘└──────────┘
typ    └─┘└──────────┘
doc    └─┘            
txt    └─┘            
par    └─┘            
pid                  
st   ──────────────────┘└─
4365    refl,
src    └──┘
typ    └──┘
doc    └──┘
txt    └──┘
par    └──┘
st   ─────┘└─
4366  end
st   ──┘
4367  
4368  theorem chain_succ_range' : ∀ s n : ℕ, chain (λ a b, b = succ a) s (range' (s+1) n)
id                                        └───┘         └──┘     └────┘     
src                                        └───┘            └──┘       └────┘   
typ                                       └───┘         └──┘     └────┘     
doc                                         └───┘                        └────┘
4369  | s 0     := chain.nil
id                └───────┘
src               └───────┘
typ               └───────┘
4370  | s (n+1) := (chain_succ_range' (s+1) n).cons rfl
id              └───────────────┘        └──┘  └─┘
src                                        └──┘  └─┘
typ             └───────────────┘        └──┘  └─┘
4371  
4372  theorem chain_lt_range' (s n : ℕ) : chain (<) s (range' (s+1) n) :=
id                                      └───┘      └────┘     
src                                     └───┘       └────┘   
typ                                     └───┘      └────┘     
doc                                      └───┘        └────┘
4373  (chain_succ_range' s n).imp (λ a b e, e.symm ▸ lt_succ_self _)
id    └───────────────┘   └─┘         └───┘  └──────────┘
src   └───────────────┘     └─┘             └───┘  └──────────┘
typ   └───────────────┘   └─┘         └───┘  └──────────┘
4374  
4375  theorem pairwise_lt_range' : ∀ s n : ℕ, pairwise (<) (range' s n)
id                                         └──────┘     └────┘  
src                                         └──────┘     └────┘
typ                                        └──────┘     └────┘  
doc                                          └──────┘      └────┘
4376  | s 0     := pairwise.nil
id                └──────────┘
src               └──────────┘
typ               └──────────┘
4377  | s (n+1) := (chain_iff_pairwise (by exact λ a b c, lt_trans)).1 (chain_lt_range' s n)
id              └────────────────┘                    └──────┘     └─────────────┘
src               └────────────────┘     └────┘ └──────┘└──────┘     └─────────────┘
typ             └────────────────┘     └────┘ └──────┘└──────┘     └─────────────┘
doc                                       └────┘ └──────┘
txt                                       └────┘ └──────┘
par                                       └────┘ └──────┘
pid                                             └──────┘
st                                       └──────────────────────┘
4378  
4379  theorem nodup_range' (s n : ℕ) : nodup (range' s n) :=
id                                   └───┘  └────┘  
src                                  └───┘  └────┘
typ                                  └───┘  └────┘  
doc                                   └───┘  └────┘
4380  (pairwise_lt_range' s n).imp (λ a b, ne_of_lt)
id    └────────────────┘   └─┘        └──────┘
src   └────────────────┘     └─┘          └──────┘
typ   └────────────────┘   └─┘        └──────┘
4381  
4382  @[simp] theorem range'_append : ∀ s m n : ℕ, range' s m ++ range' (s+m) n = range' s (n+m)
id                                              └────┘   └┘ └────┘      └────┘   
src                                              └────┘     └┘ └────┘         └────┘     
typ                                             └────┘   └┘ └────┘      └────┘   
doc    └──┘                                       └────┘        └────┘           └────┘
4383  | s 0     n := rfl
id                  └─┘
src                 └─┘
typ                 └─┘
4384  | s (m+1) n := show s :: (range' (s+1) m ++ range' (s+m+1) n) = s :: range' (s+1) (n+m),
id                     └┘  └────┘        └┘ └────┘             └┘ └────┘        
src                       └┘  └────┘        └┘ └────┘             └┘ └────┘        
typ                    └┘  └────┘        └┘ └────┘             └┘ └────┘        
doc                            └────┘            └────┘                   └────┘
4385                 by rw [add_right_comm, range'_append]
id                         └────────────┘  └───────────┘
src                    └──┘└────────────┘└┘             └─
typ                    └──┘└────────────┘└┘└───────────┘└─
doc                    └──┘              └┘             └─
txt                    └──┘              └┘             └─
par                    └──┘              └┘             └─
pid                      └┘              └┘             
st                    └─────────────────┘└─────────────┘
4386  
src  
typ  
doc  
txt  
par  
pid  
st   
4387  theorem range'_sublist_right {s m n : ℕ} : range' s m <+ range' s n ↔ m ≤ n :=
id                                             └────┘   └┘ └────┘      
src                                            └────┘     └┘ └────┘        
typ                                            └────┘   └┘ └────┘      
doc                                             └────┘        └────┘
4388  ⟨λ h, by simpa only [length_range'] using length_le_of_sublist h,
id                       └───────────┘        └──────────────────┘ 
src           └──────────┘└───────────┘└──────┘└──────────────────┘
typ          └──────────┘└───────────┘└──────┘└──────────────────┘
doc           └──────────┘             └──────┘                    
txt           └──────────┘             └──────┘                    
par           └──────────┘             └──────┘                    
pid                └──┘└┘             └────┘                    
st           └──────────────────────────────────────────────────────┘
4389   λ h, by rw [← nat.sub_add_cancel h, ← range'_append]; apply sublist_append_left⟩
id                 └────────────────┘     └───────────┘         └─────────────────┘
src           └────┘└────────────────┘ └──┘└───────────┘  └────┘└─────────────────┘
typ          └────┘└────────────────┘└──┘└───────────┘  └────┘└─────────────────┘
doc           └────┘                   └──┘               └────┘
txt           └────┘                   └──┘               └────┘
par           └────┘                   └──┘               └────┘
pid             └──┘                   └──┘                    
st           └─────────────────────────┘└───────────────┘└─────────────────────────┘
4390  
4391  theorem range'_subset_right {s m n : ℕ} : range' s m ⊆ range' s n ↔ m ≤ n :=
id                                            └────┘    └────┘      
src                                           └────┘      └────┘        
typ                                           └────┘    └────┘      
doc                                            └────┘       └────┘
4392  ⟨λ h, le_of_not_lt $ λ hn, lt_irrefl (s+n) $
id        └──────────┘     └┘  └───────┘  
src        └──────────┘         └───────┘   
typ       └──────────┘     └┘  └───────┘  
4393    (mem_range'.1 $ h $ mem_range'.2 ⟨le_add_right _ _, nat.add_lt_add_left hn s⟩).2,
id      └────────┘       └────────┘   └──────────┘      └─────────────────┘ └┘   
src     └────────┘        └────────┘   └──────────┘      └─────────────────┘       
typ     └────────┘       └────────┘   └──────────┘      └─────────────────┘ └┘   
4394   λ h, subset_of_sublist (range'_sublist_right.2 h)⟩
id        └───────────────┘  └──────────────────┘  
src        └───────────────┘  └──────────────────┘
typ       └───────────────┘  └──────────────────┘  
4395  
4396  theorem nth_range' : ∀ s {m n : ℕ}, m < n → nth (range' s n) m = some (s + m)
id                                          └─┘  └────┘      └──┘    
src                                            └─┘  └────┘         └──┘    
typ                                         └─┘  └────┘      └──┘    
doc                                                   └────┘
4397  | s 0     (n+1) _ := rfl
id                       └─┘
src                      └─┘
typ                      └─┘
4398  | s (m+1) (n+1) h := (nth_range' (s+1) (lt_of_add_lt_add_right h)).trans $ by rw add_right_comm; refl
id                     └────────┘       └────────────────────┘    └───┘          └────────────┘
src                                       └────────────────────┘    └───┘       └─┘└────────────┘  └────
typ                    └────────┘       └────────────────────┘    └───┘       └─┘└────────────┘  └────
doc                                                                                └─┘                └────
txt                                                                                └─┘                └────
par                                                                                └─┘                └────
pid                                                                                                      
st                                                                                └────────────────────────
4399  
src  
typ  
doc  
txt  
par  
pid  
st   
4400  theorem range'_concat (s n : ℕ) : range' s (n + 1) = range' s n ++ [s+n] :=
id                                    └────┘         └────┘   └┘ 
src                                   └────┘           └────┘     └┘   
typ                                   └────┘         └────┘   └┘ 
doc                                    └────┘             └────┘
4401  by rw add_comm n 1; exact (range'_append s n 1).symm
id         └──────┘            └───────────┘  
src     └─┘└──────┘ └┘  └────┘ └───────────┘  └────────
typ     └─┘└──────┘└┘  └────┘ └───────────┘└────────
doc     └─┘         └┘  └────┘                └────────
txt     └─┘         └┘  └────┘                └────────
par     └─┘         └┘  └────┘                └────────
pid                                       └─────┘└─
st     └──────────────────────────────────────────────────
4402  
src  
typ  
doc  
txt  
par  
pid  
st   
4403  theorem range_core_range' : ∀ s n : ℕ, range_core s (range' s n) = range' 0 (n + s)
id                                        └────────┘   └────┘     └────┘      
src                                        └────────┘    └────┘       └────┘      
typ                                       └────────┘   └────┘     └────┘      
doc                                                       └────┘        └────┘
4404  | 0     n := rfl
id                └─┘
src               └─┘
typ               └─┘
4405  | (s+1) n := by rw [show n+(s+1) = n+1+s, from add_right_comm n s 1]; exact range_core_range' s (n+1)
id                                               └────────────┘             └───────────────┘   
src                 └──┘        └─┘    └─────┘└────────────┘  └─┘  └────┘                     └──
typ                 └──┘        └─┘    └─────┘└────────────┘└─┘  └────┘└───────────────┘  └──
doc                  └──┘         └─┘     └─────┘                └─┘  └────┘                     └──
txt                  └──┘         └─┘     └─────┘                └─┘  └────┘                     └──
par                  └──┘         └─┘     └─────┘                └─┘  └────┘                     └──
pid                    └┘         └─┘     └─────┘                └─┘                            └┘
st                  └─────────────────────────────────────────────────┘└┘└─────────────────────────────────
4406  
src  
typ  
doc  
txt  
par  
pid  
st   
4407  theorem range_eq_range' (n : ℕ) : range n = range' 0 n :=
id                                    └───┘   └────┘   
src                                   └───┘    └────┘
typ                                   └───┘   └────┘   
doc                                              └────┘
4408  (range_core_range' n 0).trans $ by rw zero_add
id    └───────────────┘    └───┘          └──────┘
src   └───────────────┘     └───┘       └─┘└──────┘
typ   └───────────────┘    └───┘       └─┘└──────┘
doc                                     └─┘        
txt                                     └─┘        
par                                     └─┘        
pid                                               
st                                     └────────────
4409  
src  
typ  
doc  
txt  
par  
pid  
st   
4410  theorem range_succ_eq_map (n : ℕ) : range (n + 1) = 0 :: map succ (range n) :=
id                                      └───┘          └┘ └─┘ └──┘  └───┘ 
src                                     └───┘           └┘ └─┘ └──┘  └───┘
typ                                     └───┘          └┘ └─┘ └──┘  └───┘ 
4411  by rw [range_eq_range', range_eq_range', range',
id          └─────────────┘  └─────────────┘  └────┘
src     └──┘└─────────────┘└┘└─────────────┘└┘└────┘└─
typ     └──┘└─────────────┘└┘└─────────────┘└┘└────┘└─
doc     └──┘               └┘               └┘└────┘└─
txt     └──┘               └┘               └┘      └─
par     └──┘               └┘               └┘      └─
pid       └┘               └┘               └┘      └─
st     └──────────────────┘└───────────────┘└──────┘└─
4412         add_comm, ← map_add_range'];
id          └──────┘    └────────────┘
src  ──────┘└──────┘└──┘└────────────┘
typ  ──────┘└──────┘└──┘└────────────┘
doc  ──────┘        └──┘              
txt  ──────┘        └──┘              
par  ──────┘        └──┘              
pid  ──────┘        └──┘              
st   ──────────────┘└────────────────┘└─
4413     congr; exact funext one_add
id                   └────┘ └─────┘
src     └───┘  └────┘└────┘└─────┘
typ     └───┘  └────┘└────┘└─────┘
doc            └────┘             
txt     └───┘  └────┘             
par     └───┘  └────┘             
pid                              
st   ───────────────────────────────
4414  
src  
typ  
doc  
txt  
par  
pid  
st   
4415  theorem range'_eq_map_range (s n : ℕ) : range' s n = map ((+) s) (range n) :=
id                                          └────┘    └─┘        └───┘ 
src                                         └────┘      └─┘         └───┘
typ                                         └────┘    └─┘        └───┘ 
doc                                          └────┘
4416  by rw [range_eq_range', map_add_range']; refl
id          └─────────────┘  └────────────┘
src     └──┘└─────────────┘└┘└────────────┘  └────
typ     └──┘└─────────────┘└┘└────────────┘  └────
doc     └──┘               └┘                └────
txt     └──┘               └┘                └────
par     └──┘               └┘                └────
pid       └┘               └┘                    
st     └──────────────────┘└──────────────┘└──────
4417  
src  
typ  
doc  
txt  
par  
pid  
st   
4418  @[simp] theorem length_range (n : ℕ) : length (range n) = n :=
id                                         └────┘  └───┘    
src                                        └────┘  └───┘    
typ                                        └────┘  └───┘    
doc    └──┘
4419  by simp only [range_eq_range', length_range']
id                 └─────────────┘  └───────────┘
src     └─────────┘└─────────────┘└┘└───────────┘└─
typ     └─────────┘└─────────────┘└┘└───────────┘└─
doc     └─────────┘               └┘             └─
txt     └─────────┘               └┘             └─
par     └─────────┘               └┘             └─
pid         └──┘└┘               └┘             
st     └───────────────────────────────────────────
4420  
src  
typ  
doc  
txt  
par  
pid  
st   
4421  theorem pairwise_lt_range (n : ℕ) : pairwise (<) (range n) :=
id                                      └──────┘     └───┘ 
src                                     └──────┘     └───┘
typ                                     └──────┘     └───┘ 
doc                                      └──────┘
4422  by simp only [range_eq_range', pairwise_lt_range']
id                 └─────────────┘  └────────────────┘
src     └─────────┘└─────────────┘└┘└────────────────┘└─
typ     └─────────┘└─────────────┘└┘└────────────────┘└─
doc     └─────────┘               └┘                  └─
txt     └─────────┘               └┘                  └─
par     └─────────┘               └┘                  └─
pid         └──┘└┘               └┘                  
st     └────────────────────────────────────────────────
4423  
src  
typ  
doc  
txt  
par  
pid  
st   
4424  theorem nodup_range (n : ℕ) : nodup (range n) :=
id                                └───┘  └───┘ 
src                               └───┘  └───┘
typ                               └───┘  └───┘ 
doc                                └───┘
4425  by simp only [range_eq_range', nodup_range']
id                 └─────────────┘  └──────────┘
src     └─────────┘└─────────────┘└┘└──────────┘└─
typ     └─────────┘└─────────────┘└┘└──────────┘└─
doc     └─────────┘               └┘            └─
txt     └─────────┘               └┘            └─
par     └─────────┘               └┘            └─
pid         └──┘└┘               └┘            
st     └──────────────────────────────────────────
4426  
src  
typ  
doc  
txt  
par  
pid  
st   
4427  theorem range_sublist {m n : ℕ} : range m <+ range n ↔ m ≤ n :=
id                                    └───┘  └┘ └───┘     
src                                   └───┘   └┘ └───┘      
typ                                   └───┘  └┘ └───┘     
4428  by simp only [range_eq_range', range'_sublist_right]
id                 └─────────────┘  └──────────────────┘
src     └─────────┘└─────────────┘└┘└──────────────────┘└─
typ     └─────────┘└─────────────┘└┘└──────────────────┘└─
doc     └─────────┘               └┘                    └─
txt     └─────────┘               └┘                    └─
par     └─────────┘               └┘                    └─
pid         └──┘└┘               └┘                    
st     └──────────────────────────────────────────────────
4429  
src  
typ  
doc  
txt  
par  
pid  
st   
4430  theorem range_subset {m n : ℕ} : range m ⊆ range n ↔ m ≤ n :=
id                                   └───┘   └───┘     
src                                  └───┘    └───┘      
typ                                  └───┘   └───┘     
4431  by simp only [range_eq_range', range'_subset_right]
id                 └─────────────┘  └─────────────────┘
src     └─────────┘└─────────────┘└┘└─────────────────┘└─
typ     └─────────┘└─────────────┘└┘└─────────────────┘└─
doc     └─────────┘               └┘                   └─
txt     └─────────┘               └┘                   └─
par     └─────────┘               └┘                   └─
pid         └──┘└┘               └┘                   
st     └─────────────────────────────────────────────────
4432  
src  
typ  
doc  
txt  
par  
pid  
st   
4433  @[simp] theorem mem_range {m n : ℕ} : m ∈ range n ↔ m < n :=
id                                          └───┘     
src                                          └───┘      
typ                                         └───┘     
doc    └──┘
4434  by simp only [range_eq_range', mem_range', nat.zero_le, true_and, zero_add]
id                 └─────────────┘  └────────┘  └─────────┘  └──────┘  └──────┘
src     └─────────┘└─────────────┘└┘└────────┘└┘└─────────┘└┘└──────┘└┘└──────┘└─
typ     └─────────┘└─────────────┘└┘└────────┘└┘└─────────┘└┘└──────┘└┘└──────┘└─
doc     └─────────┘               └┘          └┘           └┘        └┘        └─
txt     └─────────┘               └┘          └┘           └┘        └┘        └─
par     └─────────┘               └┘          └┘           └┘        └┘        └─
pid         └──┘└┘               └┘          └┘           └┘        └┘        
st     └─────────────────────────────────────────────────────────────────────────
4435  
src  
typ  
doc  
txt  
par  
pid  
st   
4436  @[simp] theorem not_mem_range_self {n : ℕ} : n ∉ range n :=
id                                                 └───┘ 
src                                                 └───┘
typ                                                └───┘ 
doc    └──┘
4437  mt mem_range.1 $ lt_irrefl _
id   └┘ └───────┘    └───────┘
src  └┘ └───────┘    └───────┘
typ  └┘ └───────┘    └───────┘
4438  
4439  theorem nth_range {m n : ℕ} (h : m < n) : nth (range n) m = some m :=
id                                         └─┘  └───┘     └──┘ 
src                                          └─┘  └───┘       └──┘
typ                                        └─┘  └───┘     └──┘ 
4440  by simp only [range_eq_range', nth_range' _ h, zero_add]
id                 └─────────────┘  └────────┘     └──────┘
src     └─────────┘└─────────────┘└┘└────────┘└─┘ └┘└──────┘└─
typ     └─────────┘└─────────────┘└┘└────────┘└─┘└┘└──────┘└─
doc     └─────────┘               └┘          └─┘ └┘        └─
txt     └─────────┘               └┘          └─┘ └┘        └─
par     └─────────┘               └┘          └─┘ └┘        └─
pid         └──┘└┘               └┘          └─┘ └┘        
st     └──────────────────────────────────────────────────────
4441  
src  
typ  
doc  
txt  
par  
pid  
st   
4442  theorem range_concat (n : ℕ) : range (succ n) = range n ++ [n] :=
id                                 └───┘  └──┘    └───┘  └┘ 
src                                └───┘  └──┘     └───┘   └┘  
typ                                └───┘  └──┘    └───┘  └┘ 
4443  by simp only [range_eq_range', range'_concat, zero_add]
id                 └─────────────┘  └───────────┘  └──────┘
src     └─────────┘└─────────────┘└┘└───────────┘└┘└──────┘└─
typ     └─────────┘└─────────────┘└┘└───────────┘└┘└──────┘└─
doc     └─────────┘               └┘             └┘        └─
txt     └─────────┘               └┘             └┘        └─
par     └─────────┘               └┘             └┘        └─
pid         └──┘└┘               └┘             └┘        
st     └─────────────────────────────────────────────────────
4444  
src  
typ  
doc  
txt  
par  
pid  
st   
4445  theorem iota_eq_reverse_range' : ∀ n : ℕ, iota n = reverse (range' 1 n)
id                                           └──┘   └─────┘  └────┘   
src                                           └──┘    └─────┘  └────┘
typ                                          └──┘   └─────┘  └────┘   
doc                                                              └────┘
4446  | 0     := rfl
id              └─┘
src             └─┘
typ             └─┘
4447  | (n+1) := by simp only [iota, range'_concat, iota_eq_reverse_range' n, reverse_append, add_comm]; refl
id                           └──┘  └───────────┘  └────────────────────┘   └────────────┘  └──────┘
src               └─────────┘└──┘└┘└───────────┘└┘                       └┘└────────────┘└┘└──────┘  └────
typ               └─────────┘└──┘└┘└───────────┘└┘└────────────────────┘└┘└────────────┘└┘└──────┘  └────
doc                └─────────┘    └┘             └┘                       └┘              └┘          └────
txt                └─────────┘    └┘             └┘                       └┘              └┘          └────
par                └─────────┘    └┘             └┘                       └┘              └┘          └────
pid                    └──┘└┘    └┘             └┘                       └┘              └┘              
st                └──────────────────────────────────────────────────────────────────────────────────────────
4448  
src  
typ  
doc  
txt  
par  
pid  
st   
4449  @[simp] theorem length_iota (n : ℕ) : length (iota n) = n :=
id                                        └────┘  └──┘    
src                                       └────┘  └──┘    
typ                                       └────┘  └──┘    
doc    └──┘
4450  by simp only [iota_eq_reverse_range', length_reverse, length_range']
id                 └────────────────────┘  └────────────┘  └───────────┘
src     └─────────┘└────────────────────┘└┘└────────────┘└┘└───────────┘└─
typ     └─────────┘└────────────────────┘└┘└────────────┘└┘└───────────┘└─
doc     └─────────┘                      └┘              └┘             └─
txt     └─────────┘                      └┘              └┘             └─
par     └─────────┘                      └┘              └┘             └─
pid         └──┘└┘                      └┘              └┘             
st     └──────────────────────────────────────────────────────────────────
4451  
src  
typ  
doc  
txt  
par  
pid  
st   
4452  theorem pairwise_gt_iota (n : ℕ) : pairwise (>) (iota n) :=
id                                     └──────┘     └──┘ 
src                                    └──────┘     └──┘
typ                                    └──────┘     └──┘ 
doc                                     └──────┘
4453  by simp only [iota_eq_reverse_range', pairwise_reverse, pairwise_lt_range']
id                 └────────────────────┘  └──────────────┘  └────────────────┘
src     └─────────┘└────────────────────┘└┘└──────────────┘└┘└────────────────┘└─
typ     └─────────┘└────────────────────┘└┘└──────────────┘└┘└────────────────┘└─
doc     └─────────┘                      └┘                └┘                  └─
txt     └─────────┘                      └┘                └┘                  └─
par     └─────────┘                      └┘                └┘                  └─
pid         └──┘└┘                      └┘                └┘                  
st     └─────────────────────────────────────────────────────────────────────────
4454  
src  
typ  
doc  
txt  
par  
pid  
st   
4455  theorem nodup_iota (n : ℕ) : nodup (iota n) :=
id                               └───┘  └──┘ 
src                              └───┘  └──┘
typ                              └───┘  └──┘ 
doc                               └───┘
4456  by simp only [iota_eq_reverse_range', nodup_reverse, nodup_range']
id                 └────────────────────┘  └───────────┘  └──────────┘
src     └─────────┘└────────────────────┘└┘└───────────┘└┘└──────────┘└─
typ     └─────────┘└────────────────────┘└┘└───────────┘└┘└──────────┘└─
doc     └─────────┘                      └┘             └┘            └─
txt     └─────────┘                      └┘             └┘            └─
par     └─────────┘                      └┘             └┘            └─
pid         └──┘└┘                      └┘             └┘            
st     └────────────────────────────────────────────────────────────────
4457  
src  
typ  
doc  
txt  
par  
pid  
st   
4458  theorem mem_iota {m n : ℕ} : m ∈ iota n ↔ 1 ≤ m ∧ m ≤ n :=
id                                 └──┘          
src                                 └──┘            
typ                                └──┘          
4459  by simp only [iota_eq_reverse_range', mem_reverse, mem_range', add_comm, lt_succ_iff]
id                 └────────────────────┘  └─────────┘  └────────┘  └──────┘  └─────────┘
src     └─────────┘└────────────────────┘└┘└─────────┘└┘└────────┘└┘└──────┘└┘└─────────┘└─
typ     └─────────┘└────────────────────┘└┘└─────────┘└┘└────────┘└┘└──────┘└┘└─────────┘└─
doc     └─────────┘                      └┘           └┘          └┘        └┘           └─
txt     └─────────┘                      └┘           └┘          └┘        └┘           └─
par     └─────────┘                      └┘           └┘          └┘        └┘           └─
pid         └──┘└┘                      └┘           └┘          └┘        └┘           
st     └───────────────────────────────────────────────────────────────────────────────────
4460  
src  
typ  
doc  
txt  
par  
pid  
st   
4461  theorem reverse_range' : ∀ s n : ℕ,
id                                   
src                                   
typ                                  
4462    reverse (range' s n) = map (λ i, s + n - 1 - i) (range n)
id     └─────┘  └────┘     └─┘                └───┘ 
src    └─────┘  └────┘       └─┘                    └───┘
typ    └─────┘  └────┘     └─┘                └───┘ 
doc             └────┘
4463  | s 0     := rfl
id                └─┘
src               └─┘
typ               └─┘
4464  | s (n+1) := by rw [range'_concat, reverse_append, range_succ_eq_map];
id                      └───────────┘  └────────────┘  └───────────────┘
src                 └──┘└───────────┘└┘└────────────┘└┘└───────────────┘
typ                 └──┘└───────────┘└┘└────────────┘└┘└───────────────┘
doc                  └──┘             └┘              └┘                 
txt                  └──┘             └┘              └┘                 
par                  └──┘             └┘              └┘                 
pid                    └┘             └┘              └┘                 
st                  └────────────────┘└──────────────┘└─────────────────┘└─
4465    simpa only [show s + (n + 1) - 1 = s + n, from rfl, (∘),
id                                               └─┘  
src    └──────────┘        └──┘└─┘   └─────┘└─┘└┘└───
typ    └──────────┘        └──┘└─┘ └─────┘└─┘└┘└───
doc    └──────────┘         └──┘ └─┘    └─────┘   └┘ └───
txt    └──────────┘         └──┘ └─┘    └─────┘   └┘ └───
par    └──────────┘         └──┘ └─┘    └─────┘   └┘ └───
pid         └──┘└┘         └──┘ └─┘    └─────┘   └┘ └───
st   ───────────────────────────────────────────────────────────
4466      λ a i, show a - 1 - i = a - succ i, from pred_sub _ _,
id                                  └──┘         └──────┘
src  ───┘ └────┘      └─┘     └──┘ └─────┘└──────┘└─────
typ  ───┘ └────┘      └─┘    └──┘ └─────┘└──────┘└─────
doc  ───┘ └────┘      └─┘          └─────┘        └─────
txt  ───┘ └────┘      └─┘          └─────┘        └─────
par  ───┘ └────┘      └─┘          └─────┘        └─────
pid  ───┘ └────┘      └─┘          └─────┘        └─────
st   ───────────────────────────────────────────────────────────
4467      reverse_singleton, map_cons, nat.sub_zero, cons_append,
id       └───────────────┘  └──────┘  └──────────┘  └─────────┘
src  ───┘└───────────────┘└┘└──────┘└┘└──────────┘└┘└─────────┘└─
typ  ───┘└───────────────┘└┘└──────┘└┘└──────────┘└┘└─────────┘└─
doc  ───┘                 └┘        └┘            └┘           └─
txt  ───┘                 └┘        └┘            └┘           └─
par  ───┘                 └┘        └┘            └┘           └─
pid  ───┘                 └┘        └┘            └┘           └─
st   ────────────────────────────────────────────────────────────
4468      nil_append, eq_self_iff_true, true_and, map_map]
id       └────────┘  └──────────────┘  └──────┘  └─────┘
src  ───┘└────────┘└┘└──────────────┘└┘└──────┘└┘└─────┘└─
typ  ───┘└────────┘└┘└──────────────┘└┘└──────┘└┘└─────┘└─
doc  ───┘          └┘                └┘        └┘       └─
txt  ───┘          └┘                └┘        └┘       └─
par  ───┘          └┘                └┘        └┘       └─
pid  ───┘          └┘                └┘        └┘       
st   ─────────────────────────────────────────────────────
4469    using reverse_range' s n
id           └────────────┘  
src  ───────┘                
typ  ───────┘└────────────┘
doc  ───────┘                
txt  ───────┘                
par  ───────┘                
pid  ─┘└────┘                
st   ───────────────────────────
4470  
src  
typ  
doc  
txt  
par  
pid  
st   
4471  /-- All elements of `fin n`, from `0` to `n-1`. -/
4472  def fin_range (n : ℕ) : list (fin n) :=
id                          └──┘  └─┘ 
src                         └──┘  └─┘
typ                         └──┘  └─┘ 
4473  (range n).pmap fin.mk (λ _, list.mem_range.1)
id    └───┘  └──┘  └────┘      └────────────┘
src   └───┘   └──┘  └────┘       └────────────┘
typ   └───┘  └──┘  └────┘      └────────────┘
doc           └──┘
4474  
4475  @[simp] lemma mem_fin_range {n : ℕ} (a : fin n) : a ∈ fin_range n :=
id                                           └─┘       └───────┘ 
src                                          └─┘         └───────┘
typ                                          └─┘       └───────┘ 
doc    └──┘                                                └───────┘
4476  mem_pmap.2 ⟨a.1, mem_range.2 a.2, fin.eta _ _⟩
id   └──────┘      └───────┘     └─────┘
src  └──────┘       └───────┘      └─────┘
typ  └──────┘      └───────┘     └─────┘
4477  
4478  lemma nodup_fin_range (n : ℕ) : (fin_range n).nodup :=
id                                   └───────┘  └───┘
src                                  └───────┘   └───┘
typ                                  └───────┘  └───┘
doc                                   └───────┘   └───┘
4479  nodup_pmap (λ _ _ _ _, fin.veq_of_eq) (nodup_range _)
id   └────────┘         └───────────┘   └─────────┘
src  └────────┘             └───────────┘   └─────────┘
typ  └────────┘         └───────────┘   └─────────┘
4480  
4481  @[simp] lemma length_fin_range (n : ℕ) : (fin_range n).length = n :=
id                                            └───────┘  └────┘   
src                                           └───────┘   └────┘  
typ                                           └───────┘  └────┘   
doc    └──┘                                    └───────┘
4482  by rw [fin_range, length_pmap, length_range]
id          └───────┘  └─────────┘  └──────────┘
src     └──┘└───────┘└┘└─────────┘└┘└──────────┘└─
typ     └──┘└───────┘└┘└─────────┘└┘└──────────┘└─
doc     └──┘└───────┘└┘           └┘            └─
txt     └──┘         └┘           └┘            └─
par     └──┘         └┘           └┘            └─
pid       └┘         └┘           └┘            
st     └────────────┘└───────────┘└────────────┘
4483  
src  
typ  
doc  
txt  
par  
pid  
st   
4484  @[to_additive]
doc    └─────────┘
4485  theorem prod_range_succ {α : Type u} [monoid α] (f : ℕ → α) (n : ℕ) :
id                                         └────┘                  
src                                        └────┘                    
typ                                        └────┘                  
4486    ((range n.succ).map f).prod = ((range n).map f).prod * f n :=
id       └───┘ └───┘ └─┘   └──┘     └───┘  └─┘   └──┘    
src      └───┘  └───┘ └─┘    └──┘     └───┘   └─┘    └──┘  
typ      └───┘ └───┘ └─┘   └──┘     └───┘  └─┘   └──┘    
doc                          └──┘                     └──┘
4487  by rw [range_concat, map_append, map_singleton,
id          └──────────┘  └────────┘  └───────────┘
src     └──┘└──────────┘└┘└────────┘└┘└───────────┘└─
typ     └──┘└──────────┘└┘└────────┘└┘└───────────┘└─
doc     └──┘            └┘          └┘             └─
txt     └──┘            └┘          └┘             └─
par     └──┘            └┘          └┘             └─
pid       └┘            └┘          └┘             └─
st     └───────────────┘└──────────┘└─────────────┘└─
4488    prod_append, prod_cons, prod_nil, mul_one]
id     └─────────┘  └───────┘  └──────┘  └─────┘
src  ─┘└─────────┘└┘└───────┘└┘└──────┘└┘└─────┘└─
typ  ─┘└─────────┘└┘└───────┘└┘└──────┘└┘└─────┘└─
doc  ─┘           └┘         └┘        └┘       └─
txt  ─┘           └┘         └┘        └┘       └─
par  ─┘           └┘         └┘        └┘       └─
pid  ─┘           └┘         └┘        └┘       
st   ────────────┘└─────────┘└────────┘└───────┘
4489  
src  
typ  
doc  
txt  
par  
pid  
st   
4490  /--
4491  `Ico n m` is the list of natural numbers `n ≤ x < m`.
4492  (Ico stands for "interval, closed-open".)
4493  
4494  See also `data/set/intervals.lean` for `set.Ico`, modelling intervals in general preorders, and
4495  `multiset.Ico` and `finset.Ico` for `n ≤ x < m` as a multiset or as a finset.
4496  
4497  @TODO (anyone): Define `Ioo` and `Icc`, state basic lemmas about them.
4498  @TODO (anyone): Prove that `finset.Ico` and `set.Ico` agree.
4499  @TODO (anyone): Also do the versions for integers?
4500  @TODO (anyone): One could generalise even further, defining
4501  'locally finite partial orders', for which `set.Ico a b` is `[finite]`, and
4502  'locally finite total orders', for which there is a list model.
4503   -/
4504  def Ico (n m : ℕ) : list ℕ := range' n (m - n)
id                      └──┘     └────┘     
src                     └──┘     └────┘      
typ                     └──┘     └────┘     
doc                                └────┘
4505  
4506  namespace Ico
4507  
4508  theorem zero_bot (n : ℕ) : Ico 0 n = range n :=
id                             └─┘     └───┘ 
src                            └─┘      └───┘
typ                            └─┘     └───┘ 
doc                             └─┘
4509  by rw [Ico, nat.sub_zero, range_eq_range']
id          └─┘  └──────────┘  └─────────────┘
src     └──┘└─┘└┘└──────────┘└┘└─────────────┘└─
typ     └──┘└─┘└┘└──────────┘└┘└─────────────┘└─
doc     └──┘└─┘└┘            └┘               └─
txt     └──┘   └┘            └┘               └─
par     └──┘   └┘            └┘               └─
pid       └┘   └┘            └┘               
st     └──────┘└────────────┘└───────────────┘
4510  
src  
typ  
doc  
txt  
par  
pid  
st   
4511  @[simp] theorem length (n m : ℕ) : length (Ico n m) = m - n :=
id                                     └────┘  └─┘       
src                                    └────┘  └─┘         
typ                                    └────┘  └─┘       
doc    └──┘                                     └─┘
4512  by dsimp [Ico]; simp only [length_range']
id             └─┘              └───────────┘
src     └─────┘└─┘  └─────────┘└───────────┘└─
typ     └─────┘└─┘  └─────────┘└───────────┘└─
doc     └─────┘└─┘  └─────────┘             └─
txt     └─────┘     └─────────┘             └─
par     └─────┘     └─────────┘             └─
pid                   └──┘└┘             
st     └───────────────────────────────────────
4513  
src  
typ  
doc  
txt  
par  
pid  
st   
4514  theorem pairwise_lt (n m : ℕ) : pairwise (<) (Ico n m) :=
id                                  └──────┘     └─┘  
src                                 └──────┘     └─┘
typ                                 └──────┘     └─┘  
doc                                  └──────┘      └─┘
4515  by dsimp [Ico]; simp only [pairwise_lt_range']
id             └─┘              └────────────────┘
src     └─────┘└─┘  └─────────┘└────────────────┘└─
typ     └─────┘└─┘  └─────────┘└────────────────┘└─
doc     └─────┘└─┘  └─────────┘                  └─
txt     └─────┘     └─────────┘                  └─
par     └─────┘     └─────────┘                  └─
pid                   └──┘└┘                  
st     └────────────────────────────────────────────
4516  
src  
typ  
doc  
txt  
par  
pid  
st   
4517  theorem nodup (n m : ℕ) : nodup (Ico n m) :=
id                            └───┘  └─┘  
src                           └───┘  └─┘
typ                           └───┘  └─┘  
doc                            └───┘  └─┘
4518  by dsimp [Ico]; simp only [nodup_range']
id             └─┘              └──────────┘
src     └─────┘└─┘  └─────────┘└──────────┘└─
typ     └─────┘└─┘  └─────────┘└──────────┘└─
doc     └─────┘└─┘  └─────────┘            └─
txt     └─────┘     └─────────┘            └─
par     └─────┘     └─────────┘            └─
pid                   └──┘└┘            
st     └──────────────────────────────────────
4519  
src  
typ  
doc  
txt  
par  
pid  
st   
4520  @[simp] theorem mem {n m l : ℕ} : l ∈ Ico n m ↔ n ≤ l ∧ l < m :=
id                                      └─┘          
src                                      └─┘              
typ                                     └─┘          
doc    └──┘                                └─┘
4521  suffices n ≤ l ∧ l < n + (m - n) ↔ n ≤ l ∧ l < m, by simp [Ico, this],
id                                           └─┘  └──┘
src                                              └────┘└─┘└┘    
typ                                    └────┘└─┘└┘└──┘
doc                                                       └────┘└─┘└┘    
txt                                                       └────┘   └┘    
par                                                       └────┘   └┘    
pid                                                              └┘    
st                                                       └───────────────┘
4522  begin
st   └─────
4523    cases le_total n m with hnm hmn,
id           └──────┘  
src    └────┘└──────┘  └───────────┘
typ    └────┘└──────┘└───────────┘
doc    └────┘          └───────────┘
txt    └────┘          └───────────┘
par    └────┘          └───────────┘
pid                   └───────────┘
st   ────────────────────────────────┘└─
4524    { rw [nat.add_sub_of_le hnm] },
id           └───────────────┘ └─┘
src      └──┘└───────────────┘   └┘
typ      └──┘└───────────────┘└─┘└┘
doc      └──┘                    └┘
txt      └──┘                    └┘
par      └──┘                    └┘
pid        └┘                    
st   ───┘└───────────────────────┘└┘
4525    { rw [nat.sub_eq_zero_of_le hmn, add_zero],
id           └───────────────────┘ └─┘  └──────┘
src      └──┘└───────────────────┘   └┘└──────┘
typ      └──┘└───────────────────┘└─┘└┘└──────┘
doc      └──┘                        └┘        
txt      └──┘                        └┘        
par      └──┘                        └┘        
pid        └┘                        └┘        
st   ────────────────────────────────┘└────────┘└─
4526      exact and_congr_right (assume hnl, iff.intro
id             └─────────────┘              └───────┘
src      └────┘└─────────────┘       └────┘└───────┘
typ      └────┘└─────────────┘       └────┘└───────┘
doc      └────┘                      └────┘         
txt      └────┘                      └────┘         
par      └────┘                      └────┘         
pid                                 └────┘         
st   ─────────────────────────────────────────────────
4527        (assume hln, (not_le_of_gt hln hnl).elim)
id                       └──────────┘
src  ─────┘       └────┘ └──────────┘      └───────
typ  ─────┘       └────┘ └──────────┘      └───────
doc  ─────┘       └────┘                   └───────
txt  ─────┘       └────┘                   └───────
par  ─────┘       └────┘                   └───────
pid  ─────┘       └────┘                   └───────
st   ────────────────────────────────────────────────
4528        (assume hlm, lt_of_lt_of_le hlm hmn)) }
id                      └────────────┘     └─┘
src  ─────┘       └────┘└────────────┘      └─┘
typ  ─────┘       └────┘└────────────┘   └─┘└─┘
doc  ─────┘       └────┘                    └─┘
txt  ─────┘       └────┘                    └─┘
par  ─────┘       └────┘                    └─┘
pid  ─────┘       └────┘                    └┘
st   ───────────────────────────────────────────┘└─
4529  end
st   ──┘
4530  
4531  theorem eq_nil_of_le {n m : ℕ} (h : m ≤ n) : Ico n m = [] :=
id                                            └─┘    └┘
src                                             └─┘      └┘
typ                                           └─┘    └┘
doc                                               └─┘
4532  by simp [Ico, nat.sub_eq_zero_of_le h]
id            └─┘  └───────────────────┘ 
src     └────┘└─┘└┘└───────────────────┘ └─
typ     └────┘└─┘└┘└───────────────────┘└─
doc     └────┘└─┘└┘                      └─
txt     └────┘   └┘                      └─
par     └────┘   └┘                      └─
pid            └┘                      
st     └────────────────────────────────────
4533  
src  
typ  
doc  
txt  
par  
pid  
st   
4534  theorem map_add (n m k : ℕ) : (Ico n m).map ((+) k) = Ico (n + k) (m + k) :=
id                                 └─┘   └─┘         └─┘         
src                                └─┘     └─┘          └─┘           
typ                                └─┘   └─┘         └─┘         
doc                                 └─┘                    └─┘
4535  by rw [Ico, Ico, map_add_range', nat.add_sub_add_right, add_comm n k]
id          └─┘  └─┘  └────────────┘  └───────────────────┘  └──────┘  
src     └──┘└─┘└┘└─┘└┘└────────────┘└┘└───────────────────┘└┘└──────┘  └─
typ     └──┘└─┘└┘└─┘└┘└────────────┘└┘└───────────────────┘└┘└──────┘└─
doc     └──┘└─┘└┘└─┘└┘              └┘                     └┘          └─
txt     └──┘   └┘   └┘              └┘                     └┘          └─
par     └──┘   └┘   └┘              └┘                     └┘          └─
pid       └┘   └┘   └┘              └┘                     └┘          
st     └──────┘└───┘└──────────────┘└─────────────────────┘└────────────┘
4536  
src  
typ  
doc  
txt  
par  
pid  
st   
4537  theorem map_sub (n m k : ℕ) (h₁ : k ≤ n) : (Ico n m).map (λ x, x - k) = Ico (n - k) (m - k) :=
id                                           └─┘   └─┘            └─┘         
src                                            └─┘     └─┘               └─┘           
typ                                          └─┘   └─┘            └─┘         
doc                                              └─┘                         └─┘
4538  begin
st   └─────
4539    by_cases h₂ : n < m,
id                     
src    └───────┘  └─┘ 
typ    └───────┘  └─┘
doc    └───────┘  └─┘  
txt    └───────┘  └─┘  
par    └───────┘  └─┘  
pid              └─┘  
st   ────────────────────┘└─
4540    { rw [Ico, Ico],
id           └─┘  └─┘
src      └──┘└─┘└┘└─┘
typ      └──┘└─┘└┘└─┘
doc      └──┘└─┘└┘└─┘
txt      └──┘   └┘   
par      └──┘   └┘   
pid        └┘   └┘   
st   ───┘└─────┘└───┘└──
4541      rw nat.sub_sub_sub_cancel_right h₁,
id          └──────────────────────────┘ └┘
src      └─┘└──────────────────────────┘
typ      └─┘└──────────────────────────┘└┘
doc      └─┘                            
txt      └─┘                            
par      └─┘                            
pid                                    
st   ─────────────────────────────────────┘└─
4542      rw [map_sub_range' _ _ _ h₁] },
id           └────────────┘       └┘
src      └──┘└────────────┘└─────┘  └┘
typ      └──┘└────────────┘└─────┘└┘└┘
doc      └──┘              └─────┘  └┘
txt      └──┘              └─────┘  └┘
par      └──┘              └─────┘  └┘
pid        └┘              └─────┘  
st   ──────────────────────────────┘└┘
4543    { simp at h₂,
src      └────────┘
typ      └────────┘
doc      └────────┘
txt      └────────┘
par      └────────┘
pid          └───┘
st   ─────────────┘└─
4544      rw [eq_nil_of_le h₂],
id           └──────────┘ └┘
src      └──┘└──────────┘  
typ      └──┘└──────────┘└┘
doc      └──┘              
txt      └──┘              
par      └──┘              
pid        └┘              
st   ──────────────────────┘└──
4545      rw [eq_nil_of_le (nat.sub_le_sub_right h₂ _)],
id           └──────────┘  └──────────────────┘ └┘
src      └──┘└──────────┘ └──────────────────┘  └──┘
typ      └──┘└──────────┘ └──────────────────┘└┘└──┘
doc      └──┘                                   └──┘
txt      └──┘                                   └──┘
par      └──┘                                   └──┘
pid        └┘                                   └──┘
st   ───────────────────────────────────────────────┘└──
4546      refl }
src      └───┘
typ      └───┘
doc      └───┘
txt      └───┘
par      └───┘
pid          
st   ────────┘└─
4547  end
st   ──┘
4548  
4549  @[simp] theorem self_empty {n : ℕ} : Ico n n = [] :=
id                                       └─┘    └┘
src                                      └─┘      └┘
typ                                      └─┘    └┘
doc    └──┘                               └─┘
4550  eq_nil_of_le (le_refl n)
id   └──────────┘  └─────┘ 
src  └──────────┘  └─────┘
typ  └──────────┘  └─────┘ 
4551  
4552  @[simp] theorem eq_empty_iff {n m : ℕ} : Ico n m = [] ↔ m ≤ n :=
id                                           └─┘    └┘    
src                                          └─┘      └┘    
typ                                          └─┘    └┘    
doc    └──┘                                   └─┘
4553  iff.intro (assume h, nat.le_of_sub_eq_zero $ by rw [← length, h]; refl) eq_nil_of_le
id   └───────┘           └───────────────────┘            └────┘           └──────────┘
src  └───────┘            └───────────────────┘      └────┘└────┘└┘   └──┘  └──────────┘
typ  └───────┘           └───────────────────┘      └────┘└────┘└┘  └──┘  └──────────┘
doc                                                  └────┘      └┘   └──┘
txt                                                  └────┘      └┘   └──┘
par                                                  └────┘      └┘   └──┘
pid                                                    └──┘      └┘ 
st                                                  └───────────┘└─┘└────┘
4554  
4555  lemma append_consecutive {n m l : ℕ} (hnm : n ≤ m) (hml : m ≤ l) :
id                                                           
src                                                            
typ                                                          
4556    Ico n m ++ Ico m l = Ico n l :=
id     └─┘   └┘ └─┘    └─┘  
src    └─┘     └┘ └─┘      └─┘
typ    └─┘   └┘ └─┘    └─┘  
doc    └─┘        └─┘       └─┘
4557  begin
st   └─────
4558    dunfold Ico,
src    └─────────┘
typ    └─────────┘
doc    └─────────┘
txt    └─────────┘
par    └─────────┘
pid           └──┘
st   ────────────┘└─
4559    convert range'_append _ _ _,
id             └───────────┘
src    └──────┘└───────────┘└────┘
typ    └──────┘└───────────┘└────┘
doc    └──────┘             └────┘
txt    └──────┘             └────┘
par    └──────┘             └────┘
pid                        └────┘
st   ────────────────────────────┘└─
4560    { exact (nat.add_sub_of_le hnm).symm },
id              └───────────────┘ └─┘
src      └────┘ └───────────────┘   └─────┘
typ      └────┘ └───────────────┘└─┘└─────┘
doc      └────┘                     └─────┘
txt      └────┘                     └─────┘
par      └────┘                     └─────┘
pid                                └───┘└┘
st   ───┘└─────────────────────────────────┘└┘
4561    { rwa [← nat.add_sub_assoc hnm, nat.sub_add_cancel] }
id              └───────────────┘ └─┘  └────────────────┘
src      └─────┘└───────────────┘   └┘└────────────────┘└┘
typ      └─────┘└───────────────┘└─┘└┘└────────────────┘└┘
doc      └─────┘                    └┘                  └┘
txt      └─────┘                    └┘                  └┘
par      └─────┘                    └┘                  └┘
pid         └──┘                    └┘                  
st   ───────────────────────────────┘└──────────────────┘└─
4562  end
st   ──┘
4563  
4564  @[simp] lemma inter_consecutive (n m l : ℕ) : Ico n m ∩ Ico m l = [] :=
id                                                └─┘    └─┘    └┘
src                                               └─┘      └─┘      └┘
typ                                               └─┘    └─┘    └┘
doc    └──┘                                        └─┘       └─┘
4565  begin
st   └─────
4566    apply eq_nil_iff_forall_not_mem.2,
id           └───────────────────────┘
src    └────┘└───────────────────────┘└┘
typ    └────┘└───────────────────────┘└┘
doc    └────┘                         └┘
txt    └────┘                         └┘
par    └────┘                         └┘
pid                                  └┘
st   ──────────────────────────────────┘└─
4567    intro a,
src    └─────┘
typ    └─────┘
doc    └─────┘
txt    └─────┘
par    └─────┘
pid         └┘
st   ────────┘└─
4568    simp only [and_imp, not_and, not_lt, list.mem_inter, list.Ico.mem],
id                └─────┘  └─────┘  └────┘  └────────────┘  └──────────┘
src    └─────────┘└─────┘└┘└─────┘└┘└────┘└┘└────────────┘└┘└──────────┘
typ    └─────────┘└─────┘└┘└─────┘└┘└────┘└┘└────────────┘└┘└──────────┘
doc    └─────────┘       └┘       └┘      └┘              └┘            
txt    └─────────┘       └┘       └┘      └┘              └┘            
par    └─────────┘       └┘       └┘      └┘              └┘            
pid        └──┘└┘       └┘       └┘      └┘              └┘            
st   ───────────────────────────────────────────────────────────────────┘└─
4569    intros h₁ h₂ h₃,
src    └─────────────┘
typ    └─────────────┘
doc    └─────────────┘
txt    └─────────────┘
par    └─────────────┘
pid          └───────┘
st   ────────────────┘└─
4570    exfalso,
src    └─────┘
typ    └─────┘
doc    └─────┘
txt    └─────┘
par    └─────┘
st   ────────┘└─
4571    exact not_lt_of_ge h₃ h₂
id           └──────────┘ └┘ └┘
src    └────┘└──────────┘    
typ    └────┘└──────────┘└┘└┘
doc    └────┘                
txt    └────┘                
par    └────┘                
pid                         
st   ──────────────────────────┘
4572  end
st   └─┘
4573  
4574  @[simp] lemma bag_inter_consecutive (n m l : ℕ) : list.bag_inter (Ico n m) (Ico m l) = [] :=
id                                                    └────────────┘  └─┘     └─┘     └┘
src                                                   └────────────┘  └─┘       └─┘       └┘
typ                                                   └────────────┘  └─┘     └─┘     └┘
doc    └──┘                                                            └─┘       └─┘
4575  (bag_inter_nil_iff_inter_nil _ _).2 (inter_consecutive n m l)
id    └─────────────────────────┘        └───────────────┘   
src   └─────────────────────────┘        └───────────────┘
typ   └─────────────────────────┘        └───────────────┘   
4576  
4577  @[simp] theorem succ_singleton {n : ℕ} : Ico n (n+1) = [n] :=
id                                           └─┘       
src                                          └─┘          
typ                                          └─┘       
doc    └──┘                                   └─┘
4578  by dsimp [Ico]; simp [nat.add_sub_cancel_left]
id             └─┘         └─────────────────────┘
src     └─────┘└─┘  └────┘└─────────────────────┘└─
typ     └─────┘└─┘  └────┘└─────────────────────┘└─
doc     └─────┘└─┘  └────┘                       └─
txt     └─────┘     └────┘                       └─
par     └─────┘     └────┘                       └─
pid                                          
st     └────────────────────────────────────────────
4579  
src  
typ  
doc  
txt  
par  
pid  
st   
4580  theorem succ_top {n m : ℕ} (h : n ≤ m) : Ico n (m + 1) = Ico n m ++ [m] :=
id                                        └─┘         └─┘   └┘ 
src                                         └─┘           └─┘     └┘  
typ                                       └─┘         └─┘   └┘ 
doc                                           └─┘             └─┘
4581  by rwa [← succ_singleton, append_consecutive]; exact nat.le_succ _
id             └────────────┘  └────────────────┘         └─────────┘
src     └─────┘└────────────┘└┘└────────────────┘  └────┘└─────────┘└──
typ     └─────┘└────────────┘└┘└────────────────┘  └────┘└─────────┘└──
doc     └─────┘              └┘                    └────┘           └──
txt     └─────┘              └┘                    └────┘           └──
par     └─────┘              └┘                    └────┘           └──
pid        └──┘              └┘                                    └┘
st     └────────────────────┘└──────────────────┘└─────────────────────
4582  
src  
typ  
doc  
txt  
par  
pid  
st   
4583  theorem eq_cons {n m : ℕ} (h : n < m) : Ico n m = n :: Ico (n + 1) m :=
id                                       └─┘     └┘ └─┘       
src                                        └─┘        └┘ └─┘    
typ                                      └─┘     └┘ └─┘       
doc                                          └─┘            └─┘
4584  by rw [← append_consecutive (nat.le_succ n) h, succ_singleton]; refl
id            └────────────────┘  └─────────┘     └────────────┘
src     └────┘└────────────────┘ └─────────┘ └┘ └┘└────────────┘  └────
typ     └────┘└────────────────┘ └─────────┘└┘└┘└────────────┘  └────
doc     └────┘                               └┘ └┘                └────
txt     └────┘                               └┘ └┘                └────
par     └────┘                               └┘ └┘                └────
pid       └──┘                               └┘ └┘                    
st     └─────────────────────────────────────────┘└──────────────┘└──────
4585  
src  
typ  
doc  
txt  
par  
pid  
st   
4586  @[simp] theorem pred_singleton {m : ℕ} (h : 0 < m) : Ico (m - 1) m = [m - 1] :=
id                                                     └─┘            
src                                                     └─┘               
typ                                                    └─┘            
doc    └──┘                                               └─┘
4587  by dsimp [Ico]; rw nat.sub_sub_self h; simp
id             └─┘      └──────────────┘ 
src     └─────┘└─┘  └─┘└──────────────┘   └────
typ     └─────┘└─┘  └─┘└──────────────┘  └────
doc     └─────┘└─┘  └─┘                   └────
txt     └─────┘     └─┘                   └────
par     └─────┘     └─┘                   └────
pid                                        
st     └───────────────┘└──────────────┘└────────
4588  
src  
typ  
doc  
txt  
par  
pid  
st   
4589  theorem chain'_succ (n m : ℕ) : chain' (λa b, b = succ a) (Ico n m) :=
id                                  └────┘        └──┘    └─┘  
src                                 └────┘           └──┘     └─┘
typ                                 └────┘        └──┘    └─┘  
doc                                  └────┘                     └─┘
4590  begin
st   └─────
4591    by_cases n < m,
id                
src    └───────┘ 
typ    └───────┘
doc    └───────┘  
txt    └───────┘  
par    └───────┘  
pid              
st   ───────────────┘└─
4592    { rw [eq_cons h], exact chain_succ_range' _ _ },
id           └─────┘          └───────────────┘
src      └──┘└─────┘   └────┘└───────────────┘└───┘
typ      └──┘└─────┘  └────┘└───────────────┘└───┘
doc      └──┘          └────┘                 └───┘
txt      └──┘          └────┘                 └───┘
par      └──┘          └────┘                 └───┘
pid        └┘                                └──┘
st   ───┘└───────────┘└─────────────────────────────┘└┘
4593    { rw [eq_nil_of_le (le_of_not_gt h)], trivial }
id           └──────────┘  └──────────┘ 
src      └──┘└──────────┘ └──────────┘ └┘  └──────┘
typ      └──┘└──────────┘ └──────────┘└┘  └──────┘
doc      └──┘                          └┘  └──────┘
txt      └──┘                          └┘  └──────┘
par      └──┘                          └┘  └──────┘
pid        └┘                          └┘         
st   ────────────────────────────────────┘└─────────┘└─
4594  end
st   ──┘
4595  
4596  @[simp] theorem not_mem_top {n m : ℕ} : m ∉ Ico n m :=
id                                            └─┘  
src                                            └─┘
typ                                           └─┘  
doc    └──┘                                      └─┘
4597  by simp; intros; refl
src     └──┘  └────┘  └────
typ     └──┘  └────┘  └────
doc     └──┘  └────┘  └────
txt     └──┘  └────┘  └────
par     └──┘  └────┘  └────
pid                       
st     └───────────────────
4598  
src  
typ  
doc  
txt  
par  
pid  
st   
4599  lemma filter_lt_of_top_le {n m l : ℕ} (hml : m ≤ l) : (Ico n m).filter (λ x, x < l) = Ico n m :=
id                                                      └─┘   └────┘            └─┘  
src                                                       └─┘     └────┘               └─┘
typ                                                     └─┘   └────┘            └─┘  
doc                                                         └─┘                            └─┘
4600  filter_eq_self.2 $ assume k hk, lt_of_lt_of_le (mem.1 hk).2 hml
id   └────────────┘            └┘  └────────────┘  └─┘  └┘   └─┘
src  └────────────┘                 └────────────┘  └─┘     
typ  └────────────┘            └┘  └────────────┘  └─┘  └┘   └─┘
4601  
4602  lemma filter_lt_of_le_bot {n m l : ℕ} (hln : l ≤ n) : (Ico n m).filter (λ x, x < l) = [] :=
id                                                      └─┘   └────┘            └┘
src                                                       └─┘     └────┘               └┘
typ                                                     └─┘   └────┘            └┘
doc                                                         └─┘
4603  filter_eq_nil.2 $ assume k hk, not_lt_of_le $ le_trans hln $ (mem.1 hk).1
id   └───────────┘            └┘  └──────────┘   └──────┘ └─┘    └─┘  └┘ 
src  └───────────┘                 └──────────┘   └──────┘        └─┘     
typ  └───────────┘            └┘  └──────────┘   └──────┘ └─┘    └─┘  └┘ 
4604  
4605  lemma filter_lt_of_ge {n m l : ℕ} (hlm : l ≤ m) : (Ico n m).filter (λ x, x < l) = Ico n l :=
id                                                  └─┘   └────┘            └─┘  
src                                                   └─┘     └────┘               └─┘
typ                                                 └─┘   └────┘            └─┘  
doc                                                     └─┘                            └─┘
4606  begin
st   └─────
4607    cases le_total n l with hnl hln,
id           └──────┘  
src    └────┘└──────┘  └───────────┘
typ    └────┘└──────┘└───────────┘
doc    └────┘          └───────────┘
txt    └────┘          └───────────┘
par    └────┘          └───────────┘
pid                   └───────────┘
st   ────────────────────────────────┘└─
4608    { rw [← append_consecutive hnl hlm, filter_append,
id             └────────────────┘ └─┘ └─┘  └───────────┘
src      └────┘└────────────────┘      └┘└───────────┘└─
typ      └────┘└────────────────┘└─┘└─┘└┘└───────────┘└─
doc      └────┘                        └┘             └─
txt      └────┘                        └┘             └─
par      └────┘                        └┘             └─
pid        └──┘                        └┘             └─
st   ───┘└──────────────────────────────┘└─────────────┘└─
4609        filter_lt_of_top_le (le_refl l), filter_lt_of_le_bot (le_refl l), append_nil] },
id         └─────────────────┘  └─────┘    └─────────────────┘  └─────┘    └────────┘
src  ─────┘└─────────────────┘ └─────┘ └─┘└─────────────────┘ └─────┘ └─┘└────────┘└┘
typ  ─────┘└─────────────────┘ └─────┘└─┘└─────────────────┘ └─────┘└─┘└────────┘└┘
doc  ─────┘                            └─┘                            └─┘          └┘
txt  ─────┘                            └─┘                            └─┘          └┘
par  ─────┘                            └─┘                            └─┘          └┘
pid  ─────┘                            └─┘                            └─┘          
st   ────────────────────────────────────┘└───────────────────────────────┘└──────────┘└┘
4610    { rw [eq_nil_of_le hln, filter_lt_of_le_bot hln] }
id           └──────────┘ └─┘  └─────────────────┘ └─┘
src      └──┘└──────────┘   └┘└─────────────────┘   └┘
typ      └──┘└──────────┘└─┘└┘└─────────────────┘└─┘└┘
doc      └──┘               └┘                      └┘
txt      └──┘               └┘                      └┘
par      └──┘               └┘                      └┘
pid        └┘               └┘                      
st   ───────────────────────┘└───────────────────────┘└─
4611  end
st   ──┘
4612  
4613  @[simp] lemma filter_lt (n m l : ℕ) : (Ico n m).filter (λ x, x < l) = Ico n (min m l) :=
id                                         └─┘   └────┘            └─┘   └─┘  
src                                        └─┘     └────┘               └─┘    └─┘
typ                                        └─┘   └────┘            └─┘   └─┘  
doc    └──┘                                 └─┘                            └─┘
4614  begin
st   └─────
4615    cases le_total m l with hml hlm,
id           └──────┘  
src    └────┘└──────┘  └───────────┘
typ    └────┘└──────┘└───────────┘
doc    └────┘          └───────────┘
txt    └────┘          └───────────┘
par    └────┘          └───────────┘
pid                   └───────────┘
st   ────────────────────────────────┘└─
4616    { rw [min_eq_left hml, filter_lt_of_top_le hml] },
id           └─────────┘ └─┘  └─────────────────┘ └─┘
src      └──┘└─────────┘   └┘└─────────────────┘   └┘
typ      └──┘└─────────┘└─┘└┘└─────────────────┘└─┘└┘
doc      └──┘              └┘                      └┘
txt      └──┘              └┘                      └┘
par      └──┘              └┘                      └┘
pid        └┘              └┘                      
st   ───┘└─────────────────┘└───────────────────────┘└┘
4617    { rw [min_eq_right hlm, filter_lt_of_ge hlm] }
id           └──────────┘ └─┘  └─────────────┘ └─┘
src      └──┘└──────────┘   └┘└─────────────┘   └┘
typ      └──┘└──────────┘└─┘└┘└─────────────┘└─┘└┘
doc      └──┘               └┘                  └┘
txt      └──┘               └┘                  └┘
par      └──┘               └┘                  └┘
pid        └┘               └┘                  
st   ───────────────────────┘└───────────────────┘└─
4618  end
st   ──┘
4619  
4620  lemma filter_le_of_le_bot {n m l : ℕ} (hln : l ≤ n) : (Ico n m).filter (λ x, l ≤ x) = Ico n m :=
id                                                      └─┘   └────┘            └─┘  
src                                                       └─┘     └────┘               └─┘
typ                                                     └─┘   └────┘            └─┘  
doc                                                         └─┘                            └─┘
4621  filter_eq_self.2 $ assume k hk, le_trans hln (mem.1 hk).1
id   └────────────┘            └┘  └──────┘ └─┘  └─┘  └┘ 
src  └────────────┘                 └──────┘      └─┘     
typ  └────────────┘            └┘  └──────┘ └─┘  └─┘  └┘ 
4622  
4623  lemma filter_le_of_top_le {n m l : ℕ} (hml : m ≤ l) : (Ico n m).filter (λ x, l ≤ x) = [] :=
id                                                      └─┘   └────┘            └┘
src                                                       └─┘     └────┘               └┘
typ                                                     └─┘   └────┘            └┘
doc                                                         └─┘
4624  filter_eq_nil.2 $ assume k hk, not_le_of_gt (lt_of_lt_of_le (mem.1 hk).2 hml)
id   └───────────┘            └┘  └──────────┘  └────────────┘  └─┘  └┘   └─┘
src  └───────────┘                 └──────────┘  └────────────┘  └─┘     
typ  └───────────┘            └┘  └──────────┘  └────────────┘  └─┘  └┘   └─┘
4625  
4626  lemma filter_le_of_le {n m l : ℕ} (hnl : n ≤ l) : (Ico n m).filter (λ x, l ≤ x) = Ico l m :=
id                                                  └─┘   └────┘            └─┘  
src                                                   └─┘     └────┘               └─┘
typ                                                 └─┘   └────┘            └─┘  
doc                                                     └─┘                            └─┘
4627  begin
st   └─────
4628    cases le_total l m with hlm hml,
id           └──────┘  
src    └────┘└──────┘  └───────────┘
typ    └────┘└──────┘└───────────┘
doc    └────┘          └───────────┘
txt    └────┘          └───────────┘
par    └────┘          └───────────┘
pid                   └───────────┘
st   ────────────────────────────────┘└─
4629    { rw [← append_consecutive hnl hlm, filter_append,
id             └────────────────┘ └─┘ └─┘  └───────────┘
src      └────┘└────────────────┘      └┘└───────────┘└─
typ      └────┘└────────────────┘└─┘└─┘└┘└───────────┘└─
doc      └────┘                        └┘             └─
txt      └────┘                        └┘             └─
par      └────┘                        └┘             └─
pid        └──┘                        └┘             └─
st   ───┘└──────────────────────────────┘└─────────────┘└─
4630        filter_le_of_top_le (le_refl l), filter_le_of_le_bot (le_refl l), nil_append] },
id         └─────────────────┘  └─────┘    └─────────────────┘  └─────┘    └────────┘
src  ─────┘└─────────────────┘ └─────┘ └─┘└─────────────────┘ └─────┘ └─┘└────────┘└┘
typ  ─────┘└─────────────────┘ └─────┘└─┘└─────────────────┘ └─────┘└─┘└────────┘└┘
doc  ─────┘                            └─┘                            └─┘          └┘
txt  ─────┘                            └─┘                            └─┘          └┘
par  ─────┘                            └─┘                            └─┘          └┘
pid  ─────┘                            └─┘                            └─┘          
st   ────────────────────────────────────┘└───────────────────────────────┘└──────────┘└┘
4631    { rw [eq_nil_of_le hml, filter_le_of_top_le hml] }
id           └──────────┘ └─┘  └─────────────────┘ └─┘
src      └──┘└──────────┘   └┘└─────────────────┘   └┘
typ      └──┘└──────────┘└─┘└┘└─────────────────┘└─┘└┘
doc      └──┘               └┘                      └┘
txt      └──┘               └┘                      └┘
par      └──┘               └┘                      └┘
pid        └┘               └┘                      
st   ───────────────────────┘└───────────────────────┘└─
4632  end
st   ──┘
4633  
4634  @[simp] lemma filter_le (n m l : ℕ) : (Ico n m).filter (λ x, l ≤ x) = Ico (_root_.max n l) m :=
id                                         └─┘   └────┘            └─┘  └────────┘    
src                                        └─┘     └────┘               └─┘  └────────┘
typ                                        └─┘   └────┘            └─┘  └────────┘    
doc    └──┘                                 └─┘                            └─┘
4635  begin
st   └─────
4636    cases le_total n l with hnl hln,
id           └──────┘  
src    └────┘└──────┘  └───────────┘
typ    └────┘└──────┘└───────────┘
doc    └────┘          └───────────┘
txt    └────┘          └───────────┘
par    └────┘          └───────────┘
pid                   └───────────┘
st   ────────────────────────────────┘└─
4637    { rw [max_eq_right hnl, filter_le_of_le hnl] },
id           └──────────┘ └─┘  └─────────────┘ └─┘
src      └──┘└──────────┘   └┘└─────────────┘   └┘
typ      └──┘└──────────┘└─┘└┘└─────────────┘└─┘└┘
doc      └──┘               └┘                  └┘
txt      └──┘               └┘                  └┘
par      └──┘               └┘                  └┘
pid        └┘               └┘                  
st   ───┘└──────────────────┘└───────────────────┘└┘
4638    { rw [max_eq_left hln, filter_le_of_le_bot hln] }
id           └─────────┘ └─┘  └─────────────────┘ └─┘
src      └──┘└─────────┘   └┘└─────────────────┘   └┘
typ      └──┘└─────────┘└─┘└┘└─────────────────┘└─┘└┘
doc      └──┘              └┘                      └┘
txt      └──┘              └┘                      └┘
par      └──┘              └┘                      └┘
pid        └┘              └┘                      
st   ──────────────────────┘└───────────────────────┘└─
4639  end
st   ──┘
4640  
4641  end Ico
4642  
4643  @[simp] theorem enum_from_map_fst : ∀ n (l : list α),
id                                               └──┘ 
src                                               └──┘
typ                                              └──┘ 
doc    └──┘
4644    map prod.fst (enum_from n l) = range' n l.length
id     └─┘ └──────┘  └───────┘     └────┘  └─────┘
src    └─┘ └──────┘  └───────┘       └────┘    └─────┘
typ    └─┘ └──────┘  └───────┘     └────┘  └─────┘
doc                                   └────┘
4645  | n []       := rfl
id       └┘          └─┘
src      └┘          └─┘
typ      └┘          └─┘
4646  | n (a :: l) := congr_arg (cons _) (enum_from_map_fst _ _)
id          └┘       └───────┘  └──┘     └───────────────┘
src         └┘       └───────┘  └──┘
typ         └┘       └───────┘  └──┘     └───────────────┘
4647  
4648  @[simp] theorem enum_map_fst (l : list α) :
id                                     └──┘ 
src                                    └──┘
typ                                    └──┘ 
doc    └──┘
4649    map prod.fst (enum l) = range l.length :=
id     └─┘ └──────┘  └──┘    └───┘ └─────┘
src    └─┘ └──────┘  └──┘     └───┘  └─────┘
typ    └─┘ └──────┘  └──┘    └───┘ └─────┘
4650  by simp only [enum, enum_from_map_fst, range_eq_range']
id                 └──┘  └───────────────┘  └─────────────┘
src     └─────────┘└──┘└┘└───────────────┘└┘└─────────────┘└─
typ     └─────────┘└──┘└┘└───────────────┘└┘└─────────────┘└─
doc     └─────────┘    └┘                 └┘               └─
txt     └─────────┘    └┘                 └┘               └─
par     └─────────┘    └┘                 └┘               └─
pid         └──┘└┘    └┘                 └┘               
st     └─────────────────────────────────────────────────────
4651  
src  
typ  
doc  
txt  
par  
pid  
st   
4652  theorem ilast'_mem : ∀ a l, @ilast' α a l ∈ a :: l
id                              └────┘      └┘ 
src                               └────┘          └┘
typ                             └────┘      └┘ 
doc                               └────┘
4653  | a []     := or.inl rfl
id       └┘        └────┘ └─┘
src      └┘        └────┘ └─┘
typ      └┘        └────┘ └─┘
4654  | a (b::l) := or.inr (ilast'_mem b l)
id        └┘     └────┘  └────────┘
src        └┘      └────┘
typ       └┘     └────┘  └────────┘
4655  
4656  @[simp] lemma nth_le_attach (L : list α) (i) (H : i < L.attach.length) :
id                                    └──┘              └─────┘└─────┘
src                                   └──┘                 └─────┘└─────┘
typ                                   └──┘              └─────┘└─────┘
doc    └──┘                                                 └─────┘
4657    (L.attach.nth_le i H).1 = L.nth_le i (length_attach L ▸ H) :=
id      └─────┘└─────┘      └─────┘   └───────────┘   
src      └─────┘└─────┘         └─────┘    └───────────┘   
typ     └─────┘└─────┘      └─────┘   └───────────┘   
doc      └─────┘
4658  calc  (L.attach.nth_le i H).1
id          └─────┘└─────┘   
src          └─────┘└─────┘     
typ         └─────┘└─────┘   
doc          └─────┘
4659      = (L.attach.map subtype.val).nth_le i (by simpa using H) : by rw nth_le_map'
id          └─────┘└──┘ └─────────┘ └────┘                             └─────────┘
src          └─────┘└──┘ └─────────┘ └────┘        └──────────┘        └─┘└─────────┘
typ         └─────┘└──┘ └─────────┘ └────┘       └──────────┘       └─┘└─────────┘
doc          └─────┘                               └──────────┘        └─┘           
txt                                                └──────────┘        └─┘           
par                                                └──────────┘        └─┘           
pid                                                     └────┘                     
st                                                └────────────┘      └──────────────┘
4660  ... = L.nth_le i _ : by congr; apply attach_map_val
id         └─────┘                      └────────────┘
src         └─────┘          └───┘  └────┘└────────────┘
typ        └─────┘         └───┘  └────┘└────────────┘
doc                                 └────┘              
txt                          └───┘  └────┘              
par                          └───┘  └────┘              
pid                                                    
st                          └────────────────────────────
4661  
src  
typ  
doc  
txt  
par  
pid  
st   
4662  @[simp] lemma nth_le_range {n} (i) (H : i < (range n).length) :
id                                              └───┘  └────┘
src                                              └───┘   └────┘
typ                                             └───┘  └────┘
doc    └──┘
4663    nth_le (range n) i H = i :=
id     └────┘  └───┘      
src    └────┘  └───┘        
typ    └────┘  └───┘      
4664  option.some.inj $ by rw [← nth_le_nth _, nth_range (by simpa using H)]
id   └─────────────┘            └────────┘    └───────┘                 
src  └─────────────┘      └────┘└────────┘└──┘└───────┘   └──────────┘ └──
typ  └─────────────┘      └────┘└────────┘└──┘└───────┘   └──────────┘└──
doc                       └────┘          └──┘            └──────────┘ └──
txt                       └────┘          └──┘            └──────────┘ └──
par                       └────┘          └──┘            └──────────┘ └──
pid                         └──┘          └──┘            └───────────┘ └┘
st                       └─────────────────┘└─────────────┘└────────────┘
4665  
src  
typ  
doc  
txt  
par  
pid  
st   
4666  theorem of_fn_eq_pmap {α n} {f : fin n → α} :
id                                    └─┘    
src                                   └─┘
typ                                   └─┘    
4667    of_fn f = pmap (λ i hi, f ⟨i, hi⟩) (range n) (λ _, mem_range.1) :=
id     └───┘   └──┘     └┘      └┘    └───┘        └───────┘
src    └───┘    └──┘                      └───┘          └───────┘
typ    └───┘   └──┘     └┘      └┘    └───┘        └───────┘
doc              └──┘
4668  by rw [pmap_eq_map_attach]; from ext_le (by simp)
id          └────────────────┘        └────┘
src     └──┘└────────────────┘  └───┘└────┘   └──┘└─
typ     └──┘└────────────────┘  └───┘└────┘   └──┘└─
doc     └──┘                    └───┘         └──┘└─
txt     └──┘                    └───┘         └──┘└─
par     └──┘                    └───┘         └──┘└─
pid       └┘                    └───┘         └──────
st     └─────────────────────┘└───────────────┘└───┘└─
4669    (λ i hi1 hi2, by simp at hi1; simp [nth_le_of_fn f ⟨i, hi1⟩])
id                                         └──────────┘     └─┘
src  ─┘  └──────────┘  └─────────┘└┘└────┘└──────────┘   └┘   └┘└─
typ  ─┘  └──────────┘  └─────────┘└┘└────┘└──────────┘ └┘└─┘└┘└─
doc  ─┘  └──────────┘  └─────────┘└┘└────┘               └┘   └┘└─
txt  ─┘  └──────────┘  └─────────┘└┘└────┘               └┘   └┘└─
par  ─┘  └──────────┘  └─────────┘└┘└────┘               └┘   └┘└─
pid  ─┘  └──────────┘  └──────────────────┘               └┘   └─┘
st   ─────────────────┘└──────────────────────────────────────────┘└─
4670  
src  
typ  
doc  
txt  
par  
pid  
st   
4671  theorem nodup_of_fn {α n} {f : fin n → α} (hf : function.injective f) :
id                                  └─┘            └────────────────┘ 
src                                 └─┘              └────────────────┘
typ                                 └─┘            └────────────────┘ 
4672    nodup (of_fn f) :=
id     └───┘  └───┘ 
src    └───┘  └───┘
typ    └───┘  └───┘ 
doc    └───┘
4673  by rw of_fn_eq_pmap; from nodup_pmap
id         └───────────┘       └────────┘
src     └─┘└───────────┘  └───┘└────────┘
typ     └─┘└───────────┘  └───┘└────────┘
doc     └─┘               └───┘          
txt     └─┘               └───┘          
par     └─┘               └───┘          
pid                      └───┘          
st     └──────────────────────────────────
4674    (λ _ _ _ _ H, fin.veq_of_eq $ hf H) (nodup_range n)
id                   └───────────┘   └┘     └─────────┘ 
src  ─┘  └──────────┘└───────────┘    └┘ └─────────┘ └─
typ  ─┘  └──────────┘└───────────┘ └┘ └┘ └─────────┘└─
doc  ─┘  └──────────┘                 └┘             └─
txt  ─┘  └──────────┘                 └┘             └─
par  ─┘  └──────────┘                 └┘             └─
pid  ─┘  └──────────┘                 └┘             
st   ──────────────────────────────────────────────────────
4675  
src  
typ  
doc  
txt  
par  
pid  
st   
4676  section tfae
4677  
4678  /- tfae: The Following (propositions) Are Equivalent -/
4679  
4680  theorem tfae_nil : tfae [] := forall_mem_nil _
id                      └──┘ └┘    └────────────┘
src                     └──┘ └┘    └────────────┘
typ                     └──┘ └┘    └────────────┘
4681  theorem tfae_singleton (p) : tfae [p] := by simp [tfae, -eq_iff_iff]
id                                └──┘              └──┘
src                               └──┘         └────┘└──┘└──────────────
typ                               └──┘        └────┘└──┘└──────────────
doc                                              └────┘    └──────────────
txt                                              └────┘    └──────────────
par                                              └────┘    └──────────────
pid                                                      └────────────┘
st                                              └─────────────────────────
4682  
src  
typ  
doc  
txt  
par  
pid  
st   
4683  theorem tfae_cons_of_mem {a b} {l : list Prop} (h : b ∈ l) :
id                                       └──┘              
src                                      └──┘              
typ                                      └──┘              
4684    tfae (a::l) ↔ (a ↔ b) ∧ tfae l :=
id     └──┘  └┘         └──┘ 
src    └──┘   └┘            └──┘
typ    └──┘  └┘         └──┘ 
4685  ⟨λ H, ⟨H a (by simp) b (or.inr h), λ p hp q hq, H _ (or.inr hp) _ (or.inr hq)⟩,
id                       └────┘       └┘  └┘      └────┘ └┘     └────┘ └┘
src                 └──┘     └────┘                       └────┘        └────┘
typ              └──┘    └────┘       └┘  └┘      └────┘ └┘     └────┘ └┘
doc                 └──┘
txt                 └──┘
par                 └──┘
st                 └───┘
4686  begin
st   └─────
4687     rintro ⟨ab, H⟩ p (rfl | hp) q (rfl | hq),
src     └──────────────────────────────────────┘
typ     └──────────────────────────────────────┘
doc     └──────────────────────────────────────┘
txt     └──────────────────────────────────────┘
par     └──────────────────────────────────────┘
pid           └────────────────────────────────┘
st   ──────────────────────────────────────────┘└─
4688     { refl },
src       └───┘
typ       └───┘
doc       └───┘
txt       └───┘
par       └───┘
pid           
st   ────┘└───┘└┘
4689     { exact ab.trans (H _ h _ hq) },
id              └──────┘        └┘
src       └────┘└──────┘  └─┘ └─┘  └┘
typ       └────┘└──────┘ └─┘└─┘└┘└┘
doc       └────┘          └─┘ └─┘  └┘
txt       └────┘          └─┘ └─┘  └┘
par       └────┘          └─┘ └─┘  └┘
pid                      └─┘ └─┘  
st   ────┘└──────────────────────────┘└┘
4690     { exact (ab.trans (H _ h _ hp)).symm },
id               └──────┘        └┘
src       └────┘ └──────┘  └─┘ └─┘  └──────┘
typ       └────┘ └──────┘ └─┘└─┘└┘└──────┘
doc       └────┘           └─┘ └─┘  └──────┘
txt       └────┘           └─┘ └─┘  └──────┘
par       └────┘           └─┘ └─┘  └──────┘
pid                       └─┘ └─┘  └────┘└┘
st   ────┘└─────────────────────────────────┘└┘
4691     { exact H _ hp _ hq }
id                 └┘   └┘
src       └────┘ └─┘  └─┘  
typ       └────┘└─┘└┘└─┘└┘
doc       └────┘ └─┘  └─┘  
txt       └────┘ └─┘  └─┘  
par       └────┘ └─┘  └─┘  
pid             └─┘  └─┘  
st   ──────────────────────┘└─
4692  end⟩
st   ──┘
4693  
4694  theorem tfae_cons_cons {a b} {l : list Prop} : tfae (a::b::l) ↔ (a ↔ b) ∧ tfae (b::l) :=
id                                     └──┘         └──┘  └┘└┘         └──┘  └┘
src                                    └──┘         └──┘   └┘ └┘            └──┘   └┘
typ                                    └──┘         └──┘  └┘└┘         └──┘  └┘
4695  tfae_cons_of_mem (or.inl rfl)
id   └──────────────┘  └────┘ └─┘
src  └──────────────┘  └────┘ └─┘
typ  └──────────────┘  └────┘ └─┘
4696  
4697  theorem tfae_of_forall (b : Prop) (l : list Prop) (h : ∀ a ∈ l, a ↔ b) : tfae l :=
id                                          └──┘                         └──┘ 
src                                         └──┘                             └──┘
typ                                         └──┘                         └──┘ 
4698  λ a₁ h₁ a₂ h₂, (h _ h₁).trans (h _ h₂).symm
id     └┘ └┘ └┘ └┘      └┘ └───┘      └┘ └──┘
src                         └───┘          └──┘
typ    └┘ └┘ └┘ └┘      └┘ └───┘      └┘ └──┘
4699  
4700  theorem tfae_of_cycle {a b} {l : list Prop} :
id                                    └──┘
src                                   └──┘
typ                                   └──┘
4701    list.chain (→) a (b::l) → (ilast' b l → a) → tfae (a::b::l) :=
id     └────────┘      └┘     └────┘        └──┘  └┘└┘
src    └────────┘         └┘      └────┘            └──┘   └┘ └┘
typ    └────────┘      └┘     └────┘        └──┘  └┘└┘
doc    └────────┘                 └────┘
4702  begin
st   └─────
4703    induction l with c l IH generalizing a b; simp only [tfae_cons_cons, tfae_singleton, and_true, chain_cons, chain.nil] at *,
id                                                         └────────────┘  └────────────┘  └──────┘  └────────┘  └───────┘
src    └────────┘ └───────────────────────────┘  └─────────┘└────────────┘└┘└────────────┘└┘└──────┘└┘└────────┘└┘└───────┘└────┘
typ    └────────┘└───────────────────────────┘  └─────────┘└────────────┘└┘└────────────┘└┘└──────┘└┘└────────┘└┘└───────┘└────┘
doc    └────────┘ └───────────────────────────┘  └─────────┘              └┘              └┘        └┘          └┘         └────┘
txt    └────────┘ └───────────────────────────┘  └─────────┘              └┘              └┘        └┘          └┘         └────┘
par    └────────┘ └───────────────────────────┘  └─────────┘              └┘              └┘        └┘          └┘         └────┘
pid              └─────────┘└───────────────┘      └──┘└┘              └┘              └┘        └┘          └┘         └──┘
st   ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘└─
4704    { intros a b, exact iff.intro a b },
id                         └───────┘  
src      └────────┘  └────┘└───────┘  
typ      └────────┘  └────┘└───────┘
doc      └────────┘  └────┘           
txt      └────────┘  └────┘           
par      └────────┘  └────┘           
pid            └──┘                  
st   ───┘└────────┘└────────────────────┘└┘
4705    rintros ⟨ab,⟨bc,ch⟩⟩ la,
src    └─────────────────────┘
typ    └─────────────────────┘
doc    └─────────────────────┘
txt    └─────────────────────┘
par    └─────────────────────┘
pid           └──────────────┘
st   ────────────────────────┘└─
4706    have := IH ⟨bc,ch⟩ (ab ∘ la),
id             └┘  └┘ └┘   └┘  └┘
src    └──────┘       └┘     
typ    └──────┘└┘ └┘└┘└┘ └┘└┘
doc    └──────┘       └┘      
txt    └──────┘       └┘      
par    └──────┘       └┘      
pid    └───┘└─┘       └┘      
st   ─────────────────────────────┘└─
4707    exact ⟨⟨ab, la ∘ (this.2 c (or.inl rfl) _ (ilast'_mem _ _)).1 ∘ bc⟩, this⟩
id             └┘  └┘             └────┘ └─┘     └────────┘           └┘   └──┘
src    └────┘    └┘        └─┘  └────┘└─┘└──┘ └────────┘└───────┘   └─┘    └┘
typ    └────┘  └┘└┘└┘      └─┘ └────┘└─┘└──┘ └────────┘└───────┘ └┘└─┘└──┘└┘
doc    └────┘    └┘        └─┘           └──┘           └───────┘   └─┘    └┘
txt    └────┘    └┘        └─┘           └──┘           └───────┘   └─┘    └┘
par    └────┘    └┘        └─┘           └──┘           └───────┘   └─┘    └┘
pid             └┘        └─┘           └──┘           └───────┘   └─┘    
st   ────────────────────────────────────────────────────────────────────────────┘
4708  end
st   └─┘
4709  
4710  theorem tfae.out {l} (h : tfae l) (n₁ n₂)
id                             └──┘ 
src                            └──┘
typ                            └──┘ 
4711   (h₁ : n₁ < list.length l . tactic.exact_dec_trivial)
id          └┘  └─────────┘  
src             └─────────┘
typ         └┘  └─────────┘  
doc            
4712   (h₂ : n₂ < list.length l . tactic.exact_dec_trivial) :
id          └┘  └─────────┘  
src             └─────────┘
typ         └┘  └─────────┘  
doc            
4713    list.nth_le l n₁ h₁ ↔ list.nth_le l n₂ h₂ :=
id     └─────────┘  └┘ └┘  └─────────┘  └┘ └┘
src    └─────────┘          └─────────┘
typ    └─────────┘  └┘ └┘  └─────────┘  └┘ └┘
4714  h _ (list.nth_le_mem _ _ _) _ (list.nth_le_mem _ _ _)
id       └─────────────┘           └─────────────┘
src       └─────────────┘           └─────────────┘
typ      └─────────────┘           └─────────────┘
4715  
4716  end tfae
4717  
4718  lemma rotate_mod (l : list α) (n : ℕ) : l.rotate (n % l.length) = l.rotate n :=
id                         └──┘            └─────┘    └─────┘   └─────┘ 
src                        └──┘              └─────┘      └─────┘    └─────┘
typ                        └──┘            └─────┘    └─────┘   └─────┘ 
doc                                           └─────┘                   └─────┘
4719  by simp [rotate]
id            └────┘
src     └────┘└────┘└─
typ     └────┘└────┘└─
doc     └────┘└────┘└─
txt     └────┘      └─
par     └────┘      └─
pid               
st     └──────────────
4720  
src  
typ  
doc  
txt  
par  
pid  
st   
4721  @[simp] lemma rotate_nil (n : ℕ) : ([] : list α).rotate n = [] := by cases n; refl
id                                      └┘   └──┘  └────┘    └┘             
src                                     └┘   └──┘   └────┘     └┘       └────┘   └────
typ                                     └┘   └──┘  └────┘    └┘       └────┘  └────
doc    └──┘                                          └────┘               └────┘   └────
txt                                                                       └────┘   └────
par                                                                       └────┘   └────
pid                                                                                   
st                                                                       └──────────────
4722  
src  
typ  
doc  
txt  
par  
pid  
st   
4723  @[simp] lemma rotate_zero (l : list α) : l.rotate 0 = l := by simp [rotate]
id                                  └──┘     └─────┘                 └────┘
src                                 └──┘       └─────┘            └────┘└────┘└─
typ                                 └──┘     └─────┘           └────┘└────┘└─
doc    └──┘                                    └─────┘             └────┘└────┘└─
txt                                                                └────┘      └─
par                                                                └────┘      └─
pid                                                                          
st                                                                └──────────────
4724  
src  
typ  
doc  
txt  
par  
pid  
st   
4725  @[simp] lemma rotate'_nil (n : ℕ) : ([] : list α).rotate' n = [] := by cases n; refl
id                                       └┘   └──┘  └─────┘    └┘             
src                                      └┘   └──┘   └─────┘     └┘       └────┘   └────
typ                                      └┘   └──┘  └─────┘    └┘       └────┘  └────
doc    └──┘                                           └─────┘               └────┘   └────
txt                                                                         └────┘   └────
par                                                                         └────┘   └────
pid                                                                                     
st                                                                         └──────────────
4726  
src  
typ  
doc  
txt  
par  
pid  
st   
4727  @[simp] lemma rotate'_zero (l : list α) : l.rotate' 0 = l := by cases l; refl
id                                   └──┘     └──────┘                 
src                                  └──┘       └──────┘            └────┘   └────
typ                                  └──┘     └──────┘           └────┘  └────
doc    └──┘                                     └──────┘             └────┘   └────
txt                                                                  └────┘   └────
par                                                                  └────┘   └────
pid                                                                              
st                                                                  └──────────────
4728  
src  
typ  
doc  
txt  
par  
pid  
st   
4729  lemma rotate'_cons_succ (l : list α) (a : α) (n : ℕ) :
id                                └──┘               
src                               └──┘                 
typ                               └──┘               
4730    (a :: l : list α).rotate' n.succ = (l ++ [a]).rotate' n := by simp [rotate']
id       └┘    └──┘  └─────┘  └───┘    └┘  └─────┘               └─────┘
src       └┘     └──┘   └─────┘   └───┘     └┘   └─────┘          └────┘└─────┘└─
typ      └┘    └──┘  └─────┘  └───┘    └┘  └─────┘         └────┘└─────┘└─
doc                     └─────┘                     └─────┘          └────┘└─────┘└─
txt                                                                  └────┘       └─
par                                                                  └────┘       └─
pid                                                                             
st                                                                  └───────────────
4731  
src  
typ  
doc  
txt  
par  
pid  
st   
4732  @[simp] lemma length_rotate' : ∀ (l : list α) (n : ℕ), (l.rotate' n).length = l.length
id                                        └──┘            └──────┘  └────┘   └─────┘
src                                        └──┘              └──────┘   └────┘    └─────┘
typ                                       └──┘            └──────┘  └────┘   └─────┘
doc    └──┘                                                   └──────┘
4733  | []     n     := rfl
id     └┘              └─┘
src    └┘              └─┘
typ    └┘              └─┘
4734  | (a::l) 0     := rfl
id       └┘            └─┘
src      └┘            └─┘
typ      └┘            └─┘
4735  | (a::l) (n+1) := by rw [list.rotate', length_rotate' (l ++ [a]) n]; simp
id       └┘                  └──────────┘  └────────────┘   └┘   
src      └┘              └──┘└──────────┘└┘                └┘ └┘   └────
typ      └┘              └──┘└──────────┘└┘└────────────┘ └┘└┘  └────
doc                       └──┘└──────────┘└┘                     └┘   └────
txt                       └──┘            └┘                     └┘   └────
par                       └──┘            └┘                     └┘   └────
pid                         └┘            └┘                     └┘       
st                       └───────────────┘└───────────────────────────┘└──────
4736  
src  
typ  
doc  
txt  
par  
pid  
st   
4737  lemma rotate'_eq_take_append_drop : ∀ {l : list α} {n : ℕ}, n ≤ l.length →
id                                             └──┘             └─────┘
src                                             └──┘                └─────┘
typ                                            └──┘             └─────┘
4738    l.rotate' n = l.drop n ++ l.take n
id     └──────┘   └───┘  └┘ └───┘ 
src     └──────┘     └───┘   └┘  └───┘
typ    └──────┘   └───┘  └┘ └───┘ 
doc     └──────┘
4739  | []     n     h := by simp [drop_append_of_le_length h]
id     └┘                         └──────────────────────┘ 
src    └┘                   └────┘└──────────────────────┘ └┘
typ    └┘                   └────┘└──────────────────────┘└┘
doc                         └────┘                         └┘
txt                         └────┘                         └┘
par                         └────┘                         └┘
pid                                                      
st                         └─────────────────────────────────┘
4740  | l      0     h := by simp [take_append_of_le_length h]
id                                └──────────────────────┘ 
src                         └────┘└──────────────────────┘ └┘
typ                         └────┘└──────────────────────┘└┘
doc                         └────┘                         └┘
txt                         └────┘                         └┘
par                         └────┘                         └┘
pid                                                      
st                         └─────────────────────────────────┘
4741  | (a::l) (n+1) h :=
id      └┘      
src      └┘     
typ     └┘      
4742  have hnl : n ≤ l.length, from le_of_succ_le_succ h,
id                  └─────┘       └────────────────┘
src                 └─────┘       └────────────────┘
typ                 └─────┘       └────────────────┘
4743  have hnl' : n ≤ (l ++ [a]).length,
id                     └┘   └────┘
src                    └┘   └────┘
typ                    └┘   └────┘
4744    by rw [length_append, length_cons, list.length, zero_add];
id            └───────────┘  └─────────┘  └─────────┘  └──────┘
src       └──┘└───────────┘└┘└─────────┘└┘└─────────┘└┘└──────┘
typ       └──┘└───────────┘└┘└─────────┘└┘└─────────┘└┘└──────┘
doc       └──┘             └┘           └┘           └┘        
txt       └──┘             └┘           └┘           └┘        
par       └──┘             └┘           └┘           └┘        
pid         └┘             └┘           └┘           └┘        
st       └────────────────┘└───────────┘└───────────┘└────────┘└─
4745      exact (le_of_succ_le h),
id              └───────────┘ 
src      └────┘ └───────────┘ 
typ      └────┘ └───────────┘
doc      └────┘               
txt      └────┘               
par      └────┘               
pid                          
st   ──────────────────────────┘
4746  by rw [rotate'_cons_succ, rotate'_eq_take_append_drop hnl', drop, take,
id          └───────────────┘  └─────────────────────────┘ └──┘  └──┘  └──┘
src     └──┘└───────────────┘└┘                               └┘└──┘└┘└──┘└─
typ     └──┘└───────────────┘└┘└─────────────────────────┘└──┘└┘└──┘└┘└──┘└─
doc     └──┘                 └┘                               └┘    └┘    └─
txt     └──┘                 └┘                               └┘    └┘    └─
par     └──┘                 └┘                               └┘    └┘    └─
pid       └┘                 └┘                               └┘    └┘    └─
st     └────────────────────┘└────────────────────────────────┘└────┘└────┘└─
4747       drop_append_of_le_length hnl, take_append_of_le_length hnl];
id        └──────────────────────┘ └─┘  └──────────────────────┘ └─┘
src  ────┘└──────────────────────┘   └┘└──────────────────────┘   
typ  ────┘└──────────────────────┘└─┘└┘└──────────────────────┘└─┘
doc  ────┘                           └┘                           
txt  ────┘                           └┘                           
par  ────┘                           └┘                           
pid  ────┘                           └┘                           
st   ────────────────────────────────┘└────────────────────────────┘└─
4748     simp
src     └────
typ     └────
doc     └────
txt     └────
par     └────
pid         
st   ────────
4749  
src  
typ  
doc  
txt  
par  
pid  
st   
4750  lemma rotate'_rotate' : ∀ (l : list α) (n m : ℕ), (l.rotate' n).rotate' m = l.rotate' (n + m)
id                                 └──┘              └──────┘  └─────┘    └──────┘    
src                                 └──┘                └──────┘   └─────┘      └──────┘    
typ                                └──┘              └──────┘  └─────┘    └──────┘    
doc                                                      └──────┘   └─────┘       └──────┘
4751  | (a::l) 0     m := by simp
id       └┘
src      └┘                 └───┘
typ      └┘                 └───┘
doc                         └───┘
txt                         └───┘
par                         └───┘
pid                             
st                         └────┘
4752  | []     n     m := by simp
id     └┘
src    └┘                   └───┘
typ    └┘                   └───┘
doc                         └───┘
txt                         └───┘
par                         └───┘
pid                             
st                         └────┘
4753  | (a::l) (n+1) m := by rw [rotate'_cons_succ, rotate'_rotate', add_right_comm, rotate'_cons_succ]
id       └┘                    └───────────────┘  └─────────────┘  └────────────┘  └───────────────┘
src      └┘                └──┘└───────────────┘└┘               └┘└────────────┘└┘└───────────────┘└─
typ      └┘                └──┘└───────────────┘└┘└─────────────┘└┘└────────────┘└┘└───────────────┘└─
doc                         └──┘                 └┘               └┘              └┘                 └─
txt                         └──┘                 └┘               └┘              └┘                 └─
par                         └──┘                 └┘               └┘              └┘                 └─
pid                           └┘                 └┘               └┘              └┘                 
st                         └────────────────────┘└───────────────┘└──────────────┘└─────────────────┘
4754  
src  
typ  
doc  
txt  
par  
pid  
st   
4755  @[simp] lemma rotate'_length (l : list α) : rotate' l l.length = l :=
id                                     └──┘     └─────┘  └─────┘  
src                                    └──┘      └─────┘    └─────┘ 
typ                                    └──┘     └─────┘  └─────┘  
doc    └──┘                                      └─────┘
4756  by rw rotate'_eq_take_append_drop (le_refl _); simp
id         └─────────────────────────┘  └─────┘
src     └─┘└─────────────────────────┘ └─────┘└─┘  └────
typ     └─┘└─────────────────────────┘ └─────┘└─┘  └────
doc     └─┘                                   └─┘  └────
txt     └─┘                                   └─┘  └────
par     └─┘                                   └─┘  └────
pid                                          └─┘      
st     └─────────────────────────────────────────────────
4757  
src  
typ  
doc  
txt  
par  
pid  
st   
4758  @[simp] lemma rotate'_length_mul (l : list α) : ∀ n : ℕ, l.rotate' (l.length * n) = l
id                                         └──┘            └──────┘  └─────┘     
src                                        └──┘               └──────┘   └─────┘     
typ                                        └──┘            └──────┘  └─────┘     
doc    └──┘                                                    └──────┘
4759  | 0     := by simp
src                └───┘
typ                └───┘
doc                └───┘
txt                └───┘
par                └───┘
pid                    
st                └────┘
4760  | (n+1) :=
id      
src      
typ     
4761  calc l.rotate' (l.length * (n + 1)) =
id        └──────┘  └─────┘     
src        └──────┘   └─────┘     
typ       └──────┘  └─────┘     
doc        └──────┘
4762    (l.rotate' (l.length * n)).rotate' (l.rotate' (l.length * n)).length :
id      └──────┘  └─────┘     └─────┘   └──────┘  └─────┘     └────┘
src      └──────┘   └─────┘     └─────┘    └──────┘   └─────┘     └────┘
typ     └──────┘  └─────┘     └─────┘   └──────┘  └─────┘     └────┘
doc      └──────┘                └─────┘    └──────┘
4763      by simp [-rotate'_length, nat.mul_succ, rotate'_rotate']
id                                 └──────────┘  └─────────────┘
src         └─────────────────────┘└──────────┘└┘└─────────────┘└┘
typ         └─────────────────────┘└──────────┘└┘└─────────────┘└┘
doc         └─────────────────────┘            └┘               └┘
txt         └─────────────────────┘            └┘               └┘
par         └─────────────────────┘            └┘               └┘
pid             └────────────────┘            └┘               
st         └─────────────────────────────────────────────────────┘
4764  ... = l : by rw [rotate'_length, rotate'_length_mul]
id                   └────────────┘  └────────────────┘
src               └──┘└────────────┘└┘                  └─
typ              └──┘└────────────┘└┘└────────────────┘└─
doc               └──┘              └┘                  └─
txt               └──┘              └┘                  └─
par               └──┘              └┘                  └─
pid                 └┘              └┘                  
st               └─────────────────┘└──────────────────┘
4765  
src  
typ  
doc  
txt  
par  
pid  
st   
4766  lemma rotate'_mod (l : list α) (n : ℕ) : l.rotate' (n % l.length) = l.rotate' n :=
id                          └──┘            └──────┘    └─────┘   └──────┘ 
src                         └──┘              └──────┘      └─────┘    └──────┘
typ                         └──┘            └──────┘    └─────┘   └──────┘ 
doc                                            └──────┘                   └──────┘
4767  calc l.rotate' (n % l.length) = (l.rotate' (n % l.length)).rotate'
id        └──────┘    └─────┘     └──────┘    └─────┘  └─────┘
src        └──────┘      └─────┘      └──────┘      └─────┘  └─────┘
typ       └──────┘    └─────┘     └──────┘    └─────┘  └─────┘
doc        └──────┘                    └──────┘                └─────┘
4768      ((l.rotate' (n % l.length)).length * (n / l.length)) : by rw rotate'_length_mul
id         └──────┘    └─────┘  └────┘      └─────┘           └────────────────┘
src         └──────┘      └─────┘  └────┘        └─────┘        └─┘└────────────────┘
typ        └──────┘    └─────┘  └────┘      └─────┘        └─┘└────────────────┘
doc         └──────┘                                               └─┘                  
txt                                                                └─┘                  
par                                                                └─┘                  
pid                                                                                    
st                                                                └─────────────────────┘
4769  ... = l.rotate' n : by rw [rotate'_rotate', length_rotate', nat.mod_add_div]
id         └──────┘           └─────────────┘  └────────────┘  └─────────────┘
src         └──────┘        └──┘└─────────────┘└┘└────────────┘└┘└─────────────┘└─
typ        └──────┘       └──┘└─────────────┘└┘└────────────┘└┘└─────────────┘└─
doc         └──────┘        └──┘               └┘              └┘               └─
txt                         └──┘               └┘              └┘               └─
par                         └──┘               └┘              └┘               └─
pid                           └┘               └┘              └┘               
st                         └──────────────────┘└──────────────┘└───────────────┘
4770  
src  
typ  
doc  
txt  
par  
pid  
st   
4771  lemma rotate_eq_rotate' (l : list α) (n : ℕ) : l.rotate n = l.rotate' n :=
id                                └──┘            └─────┘   └──────┘ 
src                               └──┘              └─────┘     └──────┘
typ                               └──┘            └─────┘   └──────┘ 
doc                                                  └─────┘      └──────┘
4772  if h : l.length = 0 then by simp [length_eq_zero, *] at *
id   └┘     └─────┘                  └────────────┘
src  └┘      └─────┘            └────┘└────────────┘└────────┘
typ  └┘     └─────┘            └────┘└────────────┘└────────┘
doc                              └────┘              └────────┘
txt                              └────┘              └────────┘
par                              └────┘              └────────┘
pid                                                └──┘└──┘
st                              └─────────────────────────────┘
4773  else by
st          
4774    rw [← rotate'_mod, rotate'_eq_take_append_drop (le_of_lt (nat.mod_lt _ (nat.pos_of_ne_zero h)))];
id           └─────────┘  └─────────────────────────┘  └──────┘  └────────┘    └────────────────┘ 
src    └────┘└─────────┘└┘└─────────────────────────┘ └──────┘ └────────┘└─┘ └────────────────┘ └──┘
typ    └────┘└─────────┘└┘└─────────────────────────┘ └──────┘ └────────┘└─┘ └────────────────┘└──┘
doc    └────┘           └┘                                               └─┘                    └──┘
txt    └────┘           └┘                                               └─┘                    └──┘
par    └────┘           └┘                                               └─┘                    └──┘
pid      └──┘           └┘                                               └─┘                    └──┘
st   ──────────────────┘└────────────────────────────────────────────────────────────────────────────┘└─
4775    simp [rotate]
id           └────┘
src    └────┘└────┘└─
typ    └────┘└────┘└─
doc    └────┘└────┘└─
txt    └────┘      └─
par    └────┘      └─
pid              
st   ────────────────
4776  
src  
typ  
doc  
txt  
par  
pid  
st   
4777  lemma rotate_cons_succ (l : list α) (a : α) (n : ℕ) :
id                               └──┘               
src                              └──┘                 
typ                              └──┘               
4778    (a :: l : list α).rotate n.succ = (l ++ [a]).rotate n :=
id       └┘    └──┘  └────┘  └───┘    └┘  └────┘  
src       └┘     └──┘   └────┘   └───┘     └┘   └────┘
typ      └┘    └──┘  └────┘  └───┘    └┘  └────┘  
doc                     └────┘                     └────┘
4779  by rw [rotate_eq_rotate', rotate_eq_rotate', rotate'_cons_succ]
id          └───────────────┘  └───────────────┘  └───────────────┘
src     └──┘└───────────────┘└┘└───────────────┘└┘└───────────────┘└─
typ     └──┘└───────────────┘└┘└───────────────┘└┘└───────────────┘└─
doc     └──┘                 └┘                 └┘                 └─
txt     └──┘                 └┘                 └┘                 └─
par     └──┘                 └┘                 └┘                 └─
pid       └┘                 └┘                 └┘                 
st     └────────────────────┘└─────────────────┘└─────────────────┘
4780  
src  
typ  
doc  
txt  
par  
pid  
st   
4781  @[simp] lemma mem_rotate : ∀ {l : list α} {a : α} {n : ℕ}, a ∈ l.rotate n ↔ a ∈ l
id                                    └──┘                    └─────┘     
src                                    └──┘                        └─────┘      
typ                                   └──┘                    └─────┘     
doc    └──┘                                                          └─────┘
4782  | []     _ n     := by simp
id     └┘
src    └┘                   └───┘
typ    └┘                   └───┘
doc                         └───┘
txt                         └───┘
par                         └───┘
pid                             
st                         └────┘
4783  | (a::l) _ 0     := by simp
id       └┘
src      └┘                 └───┘
typ      └┘                 └───┘
doc                         └───┘
txt                         └───┘
par                         └───┘
pid                             
st                         └────┘
4784  | (a::l) _ (n+1) := by simp [rotate_cons_succ, mem_rotate, or.comm]
id       └┘                      └──────────────┘              └─────┘
src      └┘                └────┘└──────────────┘└┘          └┘└─────┘└─
typ      └┘                └────┘└──────────────┘└┘└────────┘└┘└─────┘└─
doc                         └────┘                └┘          └┘       └─
txt                         └────┘                └┘          └┘       └─
par                         └────┘                └┘          └┘       └─
pid                                             └┘          └┘       
st                         └─────────────────────────────────────────────
4785  
src  
typ  
doc  
txt  
par  
pid  
st   
4786  @[simp] lemma length_rotate (l : list α) (n : ℕ) : (l.rotate n).length = l.length :=
id                                    └──┘             └─────┘  └────┘   └─────┘
src                                   └──┘               └─────┘   └────┘    └─────┘
typ                                   └──┘             └─────┘  └────┘   └─────┘
doc    └──┘                                               └─────┘
4787  by rw [rotate_eq_rotate', length_rotate']
id          └───────────────┘  └────────────┘
src     └──┘└───────────────┘└┘└────────────┘└─
typ     └──┘└───────────────┘└┘└────────────┘└─
doc     └──┘                 └┘              └─
txt     └──┘                 └┘              └─
par     └──┘                 └┘              └─
pid       └┘                 └┘              
st     └────────────────────┘└──────────────┘
4788  
src  
typ  
doc  
txt  
par  
pid  
st   
4789  lemma rotate_eq_take_append_drop {l : list α} {n : ℕ} : n ≤ l.length →
id                                         └──┘              └─────┘
src                                        └──┘                 └─────┘
typ                                        └──┘              └─────┘
4790    l.rotate n = l.drop n ++ l.take n :=
id     └─────┘   └───┘  └┘ └───┘ 
src     └─────┘     └───┘   └┘  └───┘
typ    └─────┘   └───┘  └┘ └───┘ 
doc     └─────┘
4791  by rw rotate_eq_rotate'; exact rotate'_eq_take_append_drop
id         └───────────────┘        └─────────────────────────┘
src     └─┘└───────────────┘  └────┘└─────────────────────────┘
typ     └─┘└───────────────┘  └────┘└─────────────────────────┘
doc     └─┘                   └────┘                           
txt     └─┘                   └────┘                           
par     └─┘                   └────┘                           
pid                                                          
st     └────────────────────────────────────────────────────────
4792  
src  
typ  
doc  
txt  
par  
pid  
st   
4793  lemma rotate_rotate (l : list α) (n m : ℕ) : (l.rotate n).rotate m = l.rotate (n + m) :=
id                            └──┘               └─────┘  └────┘    └─────┘    
src                           └──┘                 └─────┘   └────┘      └─────┘    
typ                           └──┘               └─────┘  └────┘    └─────┘    
doc                                                 └─────┘   └────┘       └─────┘
4794  by rw [rotate_eq_rotate', rotate_eq_rotate', rotate_eq_rotate', rotate'_rotate']
id          └───────────────┘  └───────────────┘  └───────────────┘  └─────────────┘
src     └──┘└───────────────┘└┘└───────────────┘└┘└───────────────┘└┘└─────────────┘└─
typ     └──┘└───────────────┘└┘└───────────────┘└┘└───────────────┘└┘└─────────────┘└─
doc     └──┘                 └┘                 └┘                 └┘               └─
txt     └──┘                 └┘                 └┘                 └┘               └─
par     └──┘                 └┘                 └┘                 └┘               └─
pid       └┘                 └┘                 └┘                 └┘               
st     └────────────────────┘└─────────────────┘└─────────────────┘└───────────────┘
4795  
src  
typ  
doc  
txt  
par  
pid  
st   
4796  @[simp] lemma rotate_length (l : list α) : rotate l l.length = l :=
id                                    └──┘     └────┘  └─────┘  
src                                   └──┘      └────┘    └─────┘ 
typ                                   └──┘     └────┘  └─────┘  
doc    └──┘                                     └────┘
4797  by rw [rotate_eq_rotate', rotate'_length]
id          └───────────────┘  └────────────┘
src     └──┘└───────────────┘└┘└────────────┘└─
typ     └──┘└───────────────┘└┘└────────────┘└─
doc     └──┘                 └┘              └─
txt     └──┘                 └┘              └─
par     └──┘                 └┘              └─
pid       └┘                 └┘              
st     └────────────────────┘└──────────────┘
4798  
src  
typ  
doc  
txt  
par  
pid  
st   
4799  @[simp] lemma rotate_length_mul (l : list α) (n : ℕ) : l.rotate (l.length * n) = l :=
id                                        └──┘            └─────┘  └─────┘     
src                                       └──┘              └─────┘   └─────┘     
typ                                       └──┘            └─────┘  └─────┘     
doc    └──┘                                                  └─────┘
4800  by rw [rotate_eq_rotate', rotate'_length_mul]
id          └───────────────┘  └────────────────┘
src     └──┘└───────────────┘└┘└────────────────┘└─
typ     └──┘└───────────────┘└┘└────────────────┘└─
doc     └──┘                 └┘                  └─
txt     └──┘                 └┘                  └─
par     └──┘                 └┘                  └─
pid       └┘                 └┘                  
st     └────────────────────┘└──────────────────┘
4801  
src  
typ  
doc  
txt  
par  
pid  
st   
4802  lemma prod_rotate_eq_one_of_prod_eq_one [group α] : ∀ {l : list α} (hl : l.prod = 1) (n : ℕ),
id                                            └───┘           └──┘         └───┘          
src                                           └───┘             └──┘           └───┘          
typ                                           └───┘           └──┘         └───┘          
doc                                                                            └───┘
4803    (l.rotate n).prod = 1
id      └─────┘  └──┘  
src      └─────┘   └──┘  
typ     └─────┘  └──┘  
doc      └─────┘   └──┘
4804  | []     _  _ := by simp
id     └┘
src    └┘                └───┘
typ    └┘                └───┘
doc                      └───┘
txt                      └───┘
par                      └───┘
pid                          
st                      └────┘
4805  | (a::l) hl n :=
id      └┘     
src      └┘
typ     └┘     
4806  have n % list.length (a :: l) ≤ list.length (a :: l), from le_of_lt (nat.mod_lt _ dec_trivial),
id           └─────────┘    └┘     └─────────┘    └┘          └──────┘  └────────┘   └─────────┘
src          └─────────┘    └┘     └─────────┘    └┘          └──────┘  └────────┘   └─────────┘
typ          └─────────┘    └┘     └─────────┘    └┘          └──────┘  └────────┘   └─────────┘
doc                                                                                    └─────────┘
4807  by rw ← list.take_append_drop (n % list.length (a :: l)) (a :: l) at hl;
id           └───────────────────┘    └─────────┘                
src     └───┘└───────────────────┘  └─────────┘     └─┘     └─────┘
typ     └───┘└───────────────────┘ └─────────┘     └─┘   └─────┘
doc     └───┘                                        └─┘     └─────┘
txt     └───┘                                        └─┘     └─────┘
par     └───┘                                        └─┘     └─────┘
pid       └─┘                                        └─┘     └────┘
st     └──────────────────────────────────────────────────────────────────────
4808    rw [← rotate_mod, rotate_eq_take_append_drop this, list.prod_append, mul_eq_one_iff_inv_eq,
id           └────────┘  └────────────────────────┘ └──┘  └──────────────┘  └───────────────────┘
src    └────┘└────────┘└┘└────────────────────────┘    └┘└──────────────┘└┘└───────────────────┘└─
typ    └────┘└────────┘└┘└────────────────────────┘└──┘└┘└──────────────┘└┘└───────────────────┘└─
doc    └────┘          └┘                              └┘                └┘                     └─
txt    └────┘          └┘                              └┘                └┘                     └─
par    └────┘          └┘                              └┘                └┘                     └─
pid      └──┘          └┘                              └┘                └┘                     └─
st   ─────┘└──────────┘└───────────────────────────────┘└────────────────┘└─────────────────────┘└─
4809      ← one_mul (list.prod _)⁻¹, ← hl, list.prod_append, mul_assoc, mul_inv_self, mul_one]
id         └─────┘  └───────┘   └┘    └┘  └──────────────┘  └───────┘  └──────────┘  └─────┘
src  ─────┘└─────┘ └───────┘└─┘└┘└──┘  └┘└──────────────┘└┘└───────┘└┘└──────────┘└┘└─────┘└─
typ  ─────┘└─────┘ └───────┘└─┘└┘└──┘└┘└┘└──────────────┘└┘└───────┘└┘└──────────┘└┘└─────┘└─
doc  ─────┘        └───────┘└─┘  └──┘  └┘                └┘         └┘            └┘       └─
txt  ─────┘                 └─┘  └──┘  └┘                └┘         └┘            └┘       └─
par  ─────┘                 └─┘  └──┘  └┘                └┘         └┘            └┘       └─
pid  ─────┘                 └─┘  └──┘  └┘                └┘         └┘            └┘       
st   ────────────────────────────┘└────┘└────────────────┘└─────────┘└────────────┘└───────┘
4810  
src  
typ  
doc  
txt  
par  
pid  
st   
4811  section choose
4812  variables (p : α → Prop) [decidable_pred p] (l : list α)
id                             └────────────┘         └──┘
src                            └────────────┘         └──┘
typ                            └────────────┘         └──┘
4813  
4814  lemma choose_spec (hp : ∃ a, a ∈ l ∧ p a) : choose p l hp ∈ l ∧ p (choose p l hp) :=
id                                      └────┘   └┘      └────┘   └┘
src                                          └────┘               └────┘
typ                                     └────┘   └┘      └────┘   └┘
4815  (choose_x p l hp).property
id    └──────┘   └┘ └──────┘
src   └──────┘        └──────┘
typ   └──────┘   └┘ └──────┘
4816  
4817  lemma choose_mem (hp : ∃ a, a ∈ l ∧ p a) : choose p l hp ∈ l := (choose_spec _ _ _).1
id                                     └────┘   └┘       └─────────┘       
src                                         └────┘               └─────────┘       
typ                                    └────┘   └┘       └─────────┘       
4818  
4819  lemma choose_property (hp : ∃ a, a ∈ l ∧ p a) : p (choose p l hp) := (choose_spec _ _ _).2
id                                            └────┘   └┘      └─────────┘       
src                                                 └────┘             └─────────┘       
typ                                           └────┘   └┘      └─────────┘       
4820  
4821  end choose
4822  
4823  
4824  namespace func
4825  
4826  variables {a : α}
4827  variables {as as1 as2 as3 : list α}
id                               └──┘
src                              └──┘
typ                              └──┘
4828  
4829  localized "notation as ` {` m ` ↦ ` a `}` := list.func.set a as m" in list.func
4830  
4831  /- set -/
4832  
4833  lemma length_set [inhabited α] : ∀ {m : ℕ} {as : list α},
id                     └───────┘                   └──┘ 
src                    └───────┘                     └──┘
typ                    └───────┘                   └──┘ 
4834    (as {m ↦ a}).length = _root_.max as.length (m+1)
id      └┘    └────┘   └────────┘ └┘└─────┘  
src             └────┘   └────────┘   └─────┘   
typ     └┘    └────┘   └────────┘ └┘└─────┘  
4835  | 0 []          := rfl
id       └┘             └─┘
src      └┘             └─┘
typ      └┘             └─┘
4836  | 0 (a::as)     := by {rw max_eq_left, refl, simp [nat.le_add_right]}
id         └┘                  └─────────┘              └──────────────┘
src        └┘               └─┘└─────────┘  └──┘  └────┘└──────────────┘
typ        └┘               └─┘└─────────┘  └──┘  └────┘└──────────────┘
doc                         └─┘             └──┘  └────┘                
txt                         └─┘             └──┘  └────┘                
par                         └─┘             └──┘  └────┘                
pid                                                                  
st                        └──────────────┘└────┘└───────────────────────┘└┘
4837  | (m+1) []      := by simp only [set, nat.zero_max, length, @length_set m]
id          └┘                       └─┘  └──────────┘  └────┘   └────────┘ 
src         └┘            └─────────┘└─┘└┘└──────────┘└┘└────┘└┘            └┘
typ         └┘            └─────────┘└─┘└┘└──────────┘└┘└────┘└┘ └────────┘└┘
doc                        └─────────┘   └┘            └┘      └┘            └┘
txt                        └─────────┘   └┘            └┘      └┘            └┘
par                        └─────────┘   └┘            └┘      └┘            └┘
pid                            └──┘└┘   └┘            └┘      └┘            
st                        └────────────────────────────────────────────────────┘
4838  | (m+1) (a::as) := by simp only [set, nat.max_succ_succ, length, @length_set m]
id            └┘                     └─┘  └───────────────┘  └────┘   └────────┘ 
src           └┘          └─────────┘└─┘└┘└───────────────┘└┘└────┘└┘            └─
typ           └┘          └─────────┘└─┘└┘└───────────────┘└┘└────┘└┘ └────────┘└─
doc                        └─────────┘   └┘                 └┘      └┘            └─
txt                        └─────────┘   └┘                 └┘      └┘            └─
par                        └─────────┘   └┘                 └┘      └┘            └─
pid                            └──┘└┘   └┘                 └┘      └┘            
st                        └──────────────────────────────────────────────────────────
4839  
src  
typ  
doc  
txt  
par  
pid  
st   
4840  @[simp] lemma get_nil [inhabited α] {k : ℕ} : get k [] = default α :=
id                          └───────┘            └─┘  └┘  └─────┘ 
src                         └───────┘             └─┘   └┘  └─────┘
typ                         └───────┘            └─┘  └┘  └─────┘ 
doc    └──┘
4841  by {cases k; refl}
id             
src      └────┘   └──┘
typ      └────┘  └──┘
doc      └────┘   └──┘
txt      └────┘   └──┘
par      └────┘   └──┘
pid           
st     └─────────────┘└┘
4842  
4843  lemma get_eq_default_of_le [inhabited α] :
id                               └───────┘ 
src                              └───────┘
typ                              └───────┘ 
4844    ∀ (k : ℕ) {as : list α}, as.length ≤ k → get k as = default α
id                   └──┘    └┘└─────┘     └─┘  └┘  └─────┘ 
src                   └──┘       └─────┘      └─┘       └─────┘
typ                  └──┘    └┘└─────┘     └─┘  └┘  └─────┘ 
4845  | 0     []      h1 := rfl
id           └┘            └─┘
src          └┘            └─┘
typ          └┘            └─┘
4846  | 0     (a::as) h1 := by cases h1
id             └┘                   └┘
src            └┘             └────┘  
typ            └┘             └────┘└┘
doc                           └────┘  
txt                           └────┘  
par                           └────┘  
pid                                  
st                           └────────┘
4847  | (k+1) []      h1 := rfl
id          └┘            └─┘
src         └┘            └─┘
typ         └┘            └─┘
4848  | (k+1) (a::as) h1 :=
id            └┘
src           └┘
typ           └┘
4849    begin
st     └─────
4850      apply get_eq_default_of_le k,
id             └──────────────────┘ 
src      └────┘                    
typ      └────┘└──────────────────┘
doc      └────┘                    
txt      └────┘                    
par      └────┘                    
pid                               
st   ───────────────────────────────┘└─
4851      rw ← nat.succ_le_succ_iff, apply h1,
id            └──────────────────┘
src      └───┘└──────────────────┘  └────┘
typ      └───┘└──────────────────┘  └────┘
doc      └───┘                      └────┘
txt      └───┘                      └────┘
par      └───┘                      └────┘
pid        └─┘                           
st   ────────────────────────────┘└────────┘└─
4852    end
st   ────┘
4853  
4854  @[simp] lemma get_set [inhabited α] {a : α} :
id                          └───────┘        
src                         └───────┘
typ                         └───────┘        
doc    └──┘
4855    ∀ {k : ℕ} {as : list α}, get k (as {k ↦ a}) = a
id                   └──┘    └─┘   └┘      
src                   └──┘     └─┘             
typ                  └──┘    └─┘   └┘      
4856  | 0 as     := by {cases as; refl, }
id                           └┘
src                    └────┘    └──┘
typ                    └────┘└┘  └──┘
doc                    └────┘    └──┘
txt                    └────┘    └──┘
par                    └────┘    └──┘
pid                         
st                   └──────────────┘└──┘
4857  | (k+1) as := by {cases as; simp [get_set]}
id                          └┘
src                   └────┘    └────┘       
typ                   └────┘└┘  └────┘└─────┘
doc                    └────┘    └────┘       
txt                    └────┘    └────┘       
par                    └────┘    └────┘       
pid                                        
st                   └────────────────────────┘└┘
4858  
4859  lemma eq_get_of_mem [inhabited α] {a : α} :
id                        └───────┘        
src                       └───────┘
typ                       └───────┘        
4860    ∀ {as : list α}, a ∈ as → ∃ n : nat, ∀ d : α, a = (get n as)
id            └──┘      └┘        └─┘            └─┘  └┘
src            └──┘                  └─┘              └─┘
typ           └──┘      └┘        └─┘            └─┘  └┘
4861  | [] h := by cases h
id     └┘               
src    └┘         └────┘ 
typ    └┘         └────┘
doc               └────┘ 
txt               └────┘ 
par               └────┘ 
pid                     
st               └───────┘
4862  | (b::as) h :=
id       └┘
src      └┘
typ      └┘
4863    begin
st     └─────
4864      rw mem_cons_iff at h, cases h,
id          └──────────┘             
src      └─┘└──────────┘└───┘  └────┘
typ      └─┘└──────────┘└───┘  └────┘
doc      └─┘            └───┘  └────┘
txt      └─┘            └───┘  └────┘
par      └─┘            └───┘  └────┘
pid                    └───┘       
st   ───────────────────────┘└───────┘└─
4865      { existsi 0, intro d, apply h },
src        └───────┘  └─────┘  └────┘ 
typ        └───────┘  └─────┘  └────┘ 
doc        └───────┘  └─────┘  └────┘ 
txt        └───────┘  └─────┘  └────┘ 
par        └───────┘  └─────┘  └────┘ 
pid                      └┘        
st   ─────┘└───────┘└───────┘└────────┘└┘
4866      { cases eq_get_of_mem h with n h2,
id               └───────────┘ 
src        └────┘              └────────┘
typ        └────┘└───────────┘└────────┘
doc        └────┘              └────────┘
txt        └────┘              └────────┘
par        └────┘              └────────┘
pid                           └────────┘
st   ────────────────────────────────────┘└─
4867        existsi (n+1), apply h2 }
id                  
src        └──────┘  └┘  └────┘  
typ        └──────┘ └┘  └────┘  
doc        └──────┘   └┘  └────┘  
txt        └──────┘   └┘  └────┘  
par        └──────┘   └┘  └────┘  
pid                  └┘         
st   ──────────────────┘└─────────┘└─
4868    end
st   ────┘
4869  
4870  lemma mem_get_of_le [inhabited α] :
id                        └───────┘ 
src                       └───────┘
typ                       └───────┘ 
4871    ∀ {n : ℕ} {as : list α}, n < as.length → get n as ∈ as
id                   └──┘      └┘└─────┘   └─┘  └┘  └┘
src                   └──┘          └─────┘   └─┘      
typ                  └──┘      └┘└─────┘   └─┘  └┘  └┘
4872  | _ [] h1 := by cases h1
id       └┘                └┘
src      └┘          └────┘  
typ      └┘          └────┘└┘
doc                  └────┘  
txt                  └────┘  
par                  └────┘  
pid                         
st                  └────────┘
4873  | 0 (a::as) _ := or.inl rfl
id         └┘         └────┘ └─┘
src        └┘         └────┘ └─┘
typ        └┘         └────┘ └─┘
4874  | (n+1) (a::as) h1 :=
id            └┘
src           └┘
typ           └┘
4875    begin
st     └─────
4876      apply or.inr, unfold get,
id             └────┘
src      └────┘└────┘  └────────┘
typ      └────┘└────┘  └────────┘
doc      └────┘        └────────┘
txt      └────┘        └────────┘
par      └────┘        └────────┘
pid                         └──┘
st   ───────────────┘└──────────┘└─
4877      apply mem_get_of_le,
src      └────┘
typ      └────┘
doc      └────┘
txt      └────┘
par      └────┘
pid           
st   ──────────────────────┘└─
4878      apply nat.lt_of_succ_lt_succ h1,
id             └────────────────────┘ └┘
src      └────┘└────────────────────┘
typ      └────┘└────────────────────┘└┘
doc      └────┘                      
txt      └────┘                      
par      └────┘                      
pid                                 
st   ──────────────────────────────────┘└─
4879    end
st   ────┘
4880  
4881  lemma mem_get_of_ne_zero [inhabited α] :
id                             └───────┘ 
src                            └───────┘
typ                            └───────┘ 
4882    ∀ {n : ℕ} {as : list α},
id                   └──┘ 
src                   └──┘
typ                  └──┘ 
4883    get n as ≠ default α → get n as ∈ as
id     └─┘  └┘  └─────┘    └─┘  └┘  └┘
src    └─┘       └─────┘     └─┘      
typ    └─┘  └┘  └─────┘    └─┘  └┘  └┘
4884  | _ [] h1 := begin exfalso, apply h1, rw get_nil end
id       └┘                                   └─────┘
src      └┘             └─────┘  └────┘    └─┘└─────┘
typ      └┘             └─────┘  └────┘    └─┘└─────┘
doc                     └─────┘  └────┘    └─┘       
txt                     └─────┘  └────┘    └─┘       
par                     └─────┘  └────┘    └─┘       
pid                                                
st                └───────────┘└────────┘└───────────┘└─┘
4885  | 0 (a::as) h1 := or.inl rfl
id         └┘          └────┘ └─┘
src        └┘          └────┘ └─┘
typ        └┘          └────┘ └─┘
4886  | (n+1) (a::as) h1 :=
id            └┘
src           └┘
typ           └┘
4887    begin
st     └─────
4888      unfold get,
src      └────────┘
typ      └────────┘
doc      └────────┘
txt      └────────┘
par      └────────┘
pid            └──┘
st   ─────────────┘└─
4889      apply (or.inr (mem_get_of_ne_zero _)),
id              └────┘  └────────────────┘
src      └────┘ └────┘                   └──┘
typ      └────┘ └────┘ └────────────────┘└──┘
doc      └────┘                          └──┘
txt      └────┘                          └──┘
par      └────┘                          └──┘
pid                                     └──┘
st   ────────────────────────────────────────┘└─
4890      apply h1
src      └────┘  
typ      └────┘  
doc      └────┘  
txt      └────┘  
par      └────┘  
pid             
st   ─────────────
4891    end
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
4892  
4893  lemma get_set_eq_of_ne [inhabited α] {a : α} :
id                           └───────┘        
src                          └───────┘
typ                          └───────┘        
4894    ∀ {as : list α} (k : ℕ) (m : ℕ),
id            └──┘               
src            └──┘                
typ           └──┘               
4895    m ≠ k → get m (as {k ↦ a}) = get m as
id          └─┘   └┘      └─┘  └┘
src           └─┘              └─┘
typ         └─┘   └┘      └─┘  └┘
4896  | as 0 m h1 :=
4897    by { cases m, contradiction, cases as;
id                                       └┘
src         └────┘   └───────────┘  └────┘
typ         └────┘  └───────────┘  └────┘└┘
doc         └────┘   └───────────┘  └────┘
txt         └────┘   └───────────┘  └────┘
par         └────┘   └───────────┘  └────┘
pid                                     
st       └────────┘└─────────────┘└───────────
4898         simp only [set, get, get_nil] }
id                     └─┘  └─┘  └─────┘
src         └─────────┘└─┘└┘└─┘└┘└─────┘└┘
typ         └─────────┘└─┘└┘└─┘└┘└─────┘└┘
doc         └─────────┘   └┘   └┘       └┘
txt         └─────────┘   └┘   └┘       └┘
par         └─────────┘   └┘   └┘       └┘
pid             └──┘└┘   └┘   └┘       
st   ────────────────────────────────────┘└┘
4899  | as (k+1) m h1 :=
id          
src         
typ         
4900    begin
st     └─────
4901      cases as; cases m,
id             └┘        
src      └────┘    └────┘
typ      └────┘└┘  └────┘
doc      └────┘    └────┘
txt      └────┘    └────┘
par      └────┘    └────┘
pid                    
st   ────────────────────┘└─
4902      simp only [set, get],
id                  └─┘  └─┘
src      └─────────┘└─┘└┘└─┘
typ      └─────────┘└─┘└┘└─┘
doc      └─────────┘   └┘   
txt      └─────────┘   └┘   
par      └─────────┘   └┘   
pid          └──┘└┘   └┘   
st   ───────────────────────┘└─
4903      { have h3 : get m (nil {k ↦ a}) = default α,
id                   └─┘   └─┘         └─────┘ 
src        └────────┘└─┘  └─┘     └┘└─────┘
typ        └────────┘└─┘ └─┘   └┘└─────┘
doc        └────────┘             └┘        
txt        └────────┘             └┘        
par        └────────┘             └┘        
pid        └─────┘└─┘             └┘        
st   ─────┘└───────────────────────────────────────┘└─
4904        { rw [get_set_eq_of_ne k m, get_nil],
id               └──────────────┘    └─────┘
src          └──┘                  └┘└─────┘
typ          └──┘└──────────────┘└┘└─────┘
doc          └──┘                  └┘       
txt          └──┘                  └┘       
par          └──┘                  └┘       
pid            └┘                  └┘       
st   ───────┘└──────────────────────┘└───────┘└──
4905          intro hc, apply h1, simp [hc] },
id                                     └┘
src          └──────┘  └────┘    └────┘  └┘
typ          └──────┘  └────┘    └────┘└┘└┘
doc          └──────┘  └────┘    └────┘  └┘
txt          └──────┘  └────┘    └────┘  └┘
par          └──────┘  └────┘    └────┘  └┘
pid               └─┘                 
st   ───────────────┘└────────┘└──────────┘└┘
4906        apply h3 },
src        └────┘  
typ        └────┘  
doc        └────┘  
txt        └────┘  
par        └────┘  
pid               
st   ──────────────┘└┘
4907      simp only [set, get],
id                  └─┘  └─┘
src      └─────────┘└─┘└┘└─┘
typ      └─────────┘└─┘└┘└─┘
doc      └─────────┘   └┘   
txt      └─────────┘   └┘   
par      └─────────┘   └┘   
pid          └──┘└┘   └┘   
st   ───────────────────────┘└─
4908      { apply get_set_eq_of_ne k m,
id               └──────────────┘  
src        └────┘                 
typ        └────┘└──────────────┘
doc        └────┘                 
txt        └────┘                 
par        └────┘                 
pid                              
st   ───────────────────────────────┘└─
4909        intro hc, apply h1, simp [hc], }
id                                   └┘
src        └──────┘  └────┘    └────┘  
typ        └──────┘  └────┘    └────┘└┘
doc        └──────┘  └────┘    └────┘  
txt        └──────┘  └────┘    └────┘  
par        └──────┘  └────┘    └────┘  
pid             └─┘                 
st   ─────────────┘└────────┘└─────────┘└───
4910    end
st   ────┘
4911  
4912  lemma get_map [inhabited α] [inhabited β] {f : α → β} :
id                  └───────┘    └───────┘           
src                 └───────┘     └───────┘
typ                 └───────┘    └───────┘           
4913    ∀ {n : ℕ} {as : list α}, n < as.length →
id                   └──┘      └┘└─────┘
src                   └──┘          └─────┘
typ                  └──┘      └┘└─────┘
4914    get n (as.map f) = f (get n as)
id     └─┘   └┘└──┘      └─┘  └┘
src    └─┘      └──┘        └─┘
typ    └─┘   └┘└──┘      └─┘  └┘
4915  | _ [] h := by cases h
id       └┘               
src      └┘         └────┘ 
typ      └┘         └────┘
doc                 └────┘ 
txt                 └────┘ 
par                 └────┘ 
pid                       
st                 └───────┘
4916  | 0 (a::as) h := rfl
id         └┘         └─┘
src        └┘         └─┘
typ        └┘         └─┘
4917  | (n+1) (a::as) h1 :=
id            └┘
src           └┘
typ           └┘
4918    begin
st     └─────
4919      have h2 : n < length as,
id                   └────┘ └┘
src      └────────┘ └────┘
typ      └────────┘└────┘└┘
doc      └────────┘        
txt      └────────┘        
par      └────────┘        
pid      └─────┘└─┘        
st   ──────────────────────────┘└─
4920      { rw [← nat.succ_le_iff, ← nat.lt_succ_iff],
id               └─────────────┘    └─────────────┘
src        └────┘└─────────────┘└──┘└─────────────┘
typ        └────┘└─────────────┘└──┘└─────────────┘
doc        └────┘               └──┘               
txt        └────┘               └──┘               
par        └────┘               └──┘               
pid          └──┘               └──┘               
st   ─────┘└───────────────────┘└─────────────────┘└──
4921        apply h1 },
src        └────┘  
typ        └────┘  
doc        └────┘  
txt        └────┘  
par        └────┘  
pid               
st   ──────────────┘└┘
4922      apply get_map h2,
id             └─────┘ └┘
src      └────┘       
typ      └────┘└─────┘└┘
doc      └────┘       
txt      └────┘       
par      └────┘       
pid                  
st   ───────────────────┘└─
4923    end
st   ────┘
4924  
4925  lemma get_map' [inhabited α] [inhabited β]
id                   └───────┘    └───────┘ 
src                  └───────┘     └───────┘
typ                  └───────┘    └───────┘ 
4926    {f : α → β} {n : ℕ} {as : list α} :
id                            └──┘ 
src                             └──┘
typ                           └──┘ 
4927    f (default α) = (default β) →
id       └─────┘     └─────┘ 
src       └─────┘      └─────┘
typ      └─────┘     └─────┘ 
4928    get n (as.map f) = f (get n as) :=
id     └─┘   └┘└──┘      └─┘  └┘
src    └─┘      └──┘        └─┘
typ    └─┘   └┘└──┘      └─┘  └┘
4929  begin
st   └─────
4930    intro h1, by_cases h2 : n < as.length,
id                               └───────┘
src    └──────┘  └───────┘  └─┘ └───────┘
typ    └──────┘  └───────┘  └─┘└───────┘
doc    └──────┘  └───────┘  └─┘  
txt    └──────┘  └───────┘  └─┘  
par    └──────┘  └───────┘  └─┘  
pid         └─┘            └─┘  
st   ─────────┘└───────────────────────────┘└─
4931    { apply get_map h2, },
id             └─────┘ └┘
src      └────┘└─────┘
typ      └────┘└─────┘└┘
doc      └────┘       
txt      └────┘       
par      └────┘       
pid                  
st   ───┘└──────────────┘└──┘
4932    { rw not_lt at h2,
id          └────┘
src      └─┘└────┘└────┘
typ      └─┘└────┘└────┘
doc      └─┘      └────┘
txt      └─┘      └────┘
par      └─┘      └────┘
pid              └────┘
st   ──────────────────┘└─
4933      rw [get_eq_default_of_le _ h2, get_eq_default_of_le, h1],
id           └──────────────────┘   └┘  └──────────────────┘  └┘
src      └──┘└──────────────────┘└─┘  └┘└──────────────────┘└┘  
typ      └──┘└──────────────────┘└─┘└┘└┘└──────────────────┘└┘└┘
doc      └──┘                    └─┘  └┘                    └┘  
txt      └──┘                    └─┘  └┘                    └┘  
par      └──┘                    └─┘  └┘                    └┘  
pid        └┘                    └─┘  └┘                    └┘  
st   ────────────────────────────────┘└────────────────────┘└──┘└──
4934      rw [length_map], apply h2 }
id           └────────┘
src      └──┘└────────┘  └────┘  
typ      └──┘└────────┘  └────┘  
doc      └──┘            └────┘  
txt      └──┘            └────┘  
par      └──┘            └────┘  
pid        └┘                   
st   ─────────────────┘└──────────┘└─
4935  end
st   ──┘
4936  
4937  lemma forall_val_of_forall_mem [inhabited α]
id                                   └───────┘ 
src                                  └───────┘
typ                                  └───────┘ 
4938    {as : list α} {p : α → Prop} :
id           └──┘        
src          └──┘
typ          └──┘        
4939    p (default α) → (∀ x ∈ as, p x) → (∀ n, p (get n as)) :=
id       └─────┘           └┘              └─┘  └┘
src       └─────┘                                 └─┘
typ      └─────┘           └┘              └─┘  └┘
4940  begin
st   └─────
4941    intros h1 h2 n,
src    └────────────┘
typ    └────────────┘
doc    └────────────┘
txt    └────────────┘
par    └────────────┘
pid          └──────┘
st   ───────────────┘└─
4942    by_cases h3 : n < as.length,
id                     └───────┘
src    └───────┘  └─┘ └───────┘
typ    └───────┘  └─┘└───────┘
doc    └───────┘  └─┘  
txt    └───────┘  └─┘  
par    └───────┘  └─┘  
pid              └─┘  
st   ────────────────────────────┘└─
4943    { apply h2 _ (mem_get_of_le h3) },
id             └┘    └───────────┘ └┘
src      └────┘  └─┘ └───────────┘  └┘
typ      └────┘└┘└─┘ └───────────┘└┘└┘
doc      └────┘  └─┘                └┘
txt      └────┘  └─┘                └┘
par      └────┘  └─┘                └┘
pid             └─┘                
st   ───┘└────────────────────────────┘└┘
4944    { rw not_lt at h3,
id          └────┘
src      └─┘└────┘└────┘
typ      └─┘└────┘└────┘
doc      └─┘      └────┘
txt      └─┘      └────┘
par      └─┘      └────┘
pid              └────┘
st   ──────────────────┘└─
4945      rw get_eq_default_of_le _ h3, apply h1 }
id          └──────────────────┘   └┘
src      └─┘└──────────────────┘└─┘    └────┘  
typ      └─┘└──────────────────┘└─┘└┘  └────┘  
doc      └─┘                    └─┘    └────┘  
txt      └─┘                    └─┘    └────┘  
par      └─┘                    └─┘    └────┘  
pid                            └─┘           
st   ───────────────────────────────┘└─────────┘└─
4946  end
st   ──┘
4947  
4948  /- equiv -/
4949  
4950  lemma equiv_refl [inhabited α] : equiv as as := λ k, rfl
id                     └───────┘     └───┘ └┘ └┘        └─┘
src                    └───────┘      └───┘               └─┘
typ                    └───────┘     └───┘ └┘ └┘        └─┘
4951  
4952  lemma equiv_symm [inhabited α] : equiv as1 as2 → equiv as2 as1 :=
id                     └───────┘     └───┘ └─┘ └─┘   └───┘ └─┘ └─┘
src                    └───────┘      └───┘           └───┘
typ                    └───────┘     └───┘ └─┘ └─┘   └───┘ └─┘ └─┘
4953  λ h1 k, (h1 k).symm
id     └┘    └┘  └──┘
src                └──┘
typ    └┘    └┘  └──┘
4954  
4955  lemma equiv_trans [inhabited α] :
id                      └───────┘ 
src                     └───────┘
typ                     └───────┘ 
4956    equiv as1 as2 → equiv as2 as3 → equiv as1 as3 :=
id     └───┘ └─┘ └─┘   └───┘ └─┘ └─┘   └───┘ └─┘ └─┘
src    └───┘           └───┘           └───┘
typ    └───┘ └─┘ └─┘   └───┘ └─┘ └─┘   └───┘ └─┘ └─┘
4957  λ h1 h2 k, eq.trans (h1 k) (h2 k)
id     └┘ └┘   └──────┘  └┘    └┘ 
src             └──────┘
typ    └┘ └┘   └──────┘  └┘    └┘ 
4958  
4959  lemma equiv_of_eq [inhabited α] : as1 = as2 → equiv as1 as2 :=
id                      └───────┘     └─┘  └─┘   └───┘ └─┘ └─┘
src                     └───────┘                 └───┘
typ                     └───────┘     └─┘  └─┘   └───┘ └─┘ └─┘
4960  begin intro h1, rw h1, apply equiv_refl end
id                      └┘        └────────┘
src        └──────┘  └─┘    └────┘└────────┘
typ        └──────┘  └─┘└┘  └────┘└────────┘
doc        └──────┘  └─┘    └────┘          
txt        └──────┘  └─┘    └────┘          
par        └──────┘  └─┘    └────┘          
pid             └─┘                       
st   └────────────┘└─────┘└─────────────────┘└─┘
4961  
4962  lemma eq_of_equiv [inhabited α] :
id                      └───────┘ 
src                     └───────┘
typ                     └───────┘ 
4963    ∀ {as1 as2 : list α}, as1.length = as2.length →
id                 └──┘    └─┘└─────┘  └─┘└─────┘
src                 └──┘        └─────┘     └─────┘
typ                └──┘    └─┘└─────┘  └─┘└─────┘
4964    equiv as1 as2 → as1 = as2
id     └───┘ └─┘ └─┘   └─┘  └─┘
src    └───┘               
typ    └───┘ └─┘ └─┘   └─┘  └─┘
4965  | []     [] h1 h2 := rfl
id     └┘     └┘          └─┘
src    └┘     └┘          └─┘
typ    └┘     └┘          └─┘
4966  | (_::_) [] h1 h2 := by cases h1
id       └┘   └┘                   └┘
src      └┘   └┘             └────┘  
typ      └┘   └┘             └────┘└┘
doc                          └────┘  
txt                          └────┘  
par                          └────┘  
pid                                 
st                          └────────┘
4967  | [] (_::_) h1 h2 := by cases h1
id     └┘   └┘                     └┘
src    └┘   └┘               └────┘  
typ    └┘   └┘               └────┘└┘
doc                          └────┘  
txt                          └────┘  
par                          └────┘  
pid                                 
st                          └────────┘
4968  | (a1::as1) (a2::as2) h1 h2 :=
id        └┘        └┘
src       └┘        └┘
typ       └┘        └┘
4969    begin
st     └─────
4970      congr,
src      └───┘
typ      └───┘
txt      └───┘
par      └───┘
st   ────────┘└─
4971      { apply h2 0 },
id               └┘
src        └────┘  └─┘
typ        └────┘└┘└─┘
doc        └────┘  └─┘
txt        └────┘  └─┘
par        └────┘  └─┘
pid               └┘
st   ─────┘└─────────┘└┘
4972      have h3 : as1.length = as2.length,
id                 └────────┘  └────────┘
src      └────────┘└────────┘└────────┘
typ      └────────┘└────────┘└────────┘
doc      └────────┘           
txt      └────────┘           
par      └────────┘           
pid      └─────┘└─┘           
st   ────────────────────────────────────┘└─
4973      { simpa [add_left_inj, add_comm, length] using h1 },
id                └──────────┘  └──────┘  └────┘        └┘
src        └─────┘└──────────┘└┘└──────┘└┘└────┘└──────┘  
typ        └─────┘└──────────┘└┘└──────┘└┘└────┘└──────┘└┘
doc        └─────┘            └┘        └┘      └──────┘  
txt        └─────┘            └┘        └┘      └──────┘  
par        └─────┘            └┘        └┘      └──────┘  
pid                         └┘        └┘      └────┘  
st   ─────┘└──────────────────────────────────────────────┘└┘
4974      apply eq_of_equiv h3,
id             └─────────┘ └┘
src      └────┘           
typ      └────┘└─────────┘└┘
doc      └────┘           
txt      └────┘           
par      └────┘           
pid                      
st   ───────────────────────┘└─
4975      intro m, apply h2 (m+1)
id                      └┘  
src      └─────┘  └────┘    └──
typ      └─────┘  └────┘└┘ └──
doc      └─────┘  └────┘     └──
txt      └─────┘  └────┘     └──
par      └─────┘  └────┘     └──
pid           └┘            └┘
st   ──────────┘└────────────────
4976    end
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
4977  
4978  /- neg -/
4979  
4980  @[simp] lemma get_neg [inhabited α] [add_group α]
id                          └───────┘    └───────┘ 
src                         └───────┘     └───────┘
typ                         └───────┘    └───────┘ 
doc    └──┘
4981    {k : ℕ} {as : list α} : @get α ⟨0⟩ k (neg as) = -(@get α ⟨0⟩ k as) :=
id                  └──┘      └─┘        └─┘ └┘     └─┘       └┘
src                 └──┘       └─┘          └─┘        └─┘
typ                 └──┘      └─┘        └─┘ └┘     └─┘       └┘
4982  by {unfold neg, rw (@get_map' α α ⟨0⟩), apply neg_zero}
id                        └──────┘                └──────┘
src      └────────┘  └─┘  └──────┘   └─┘  └────┘└──────┘
typ      └────────┘  └─┘  └──────┘  └─┘  └────┘└──────┘
doc      └────────┘  └─┘             └─┘  └────┘
txt      └────────┘  └─┘             └─┘  └────┘
par      └────────┘  └─┘             └─┘  └────┘
pid            └──┘                 └─┘       
st     └──────────┘└──────────────────────┘└──────────────┘└┘
4983  
4984  @[simp] lemma length_neg
doc    └──┘
4985    [inhabited α] [has_neg α] (as : list α) :
id      └───────┘    └─────┘         └──┘ 
src     └───────┘     └─────┘          └──┘
typ     └───────┘    └─────┘         └──┘ 
4986    (neg as).length = as.length :=
id      └─┘ └┘ └────┘   └┘└─────┘
src     └─┘    └────┘     └─────┘
typ     └─┘ └┘ └────┘   └┘└─────┘
4987  by simp only [neg, length_map]
id                 └─┘  └────────┘
src     └─────────┘└─┘└┘└────────┘└─
typ     └─────────┘└─┘└┘└────────┘└─
doc     └─────────┘   └┘          └─
txt     └─────────┘   └┘          └─
par     └─────────┘   └┘          └─
pid         └──┘└┘   └┘          
st     └────────────────────────────
4988  
src  
typ  
doc  
txt  
par  
pid  
st   
4989  /- pointwise -/
src  ────────────────
typ  ────────────────
doc  ────────────────
txt  ────────────────
par  ────────────────
pid  ────────────────
st   ────────────────
4990  
src  
typ  
doc  
txt  
par  
pid  
st   
4991  lemma nil_pointwise [inhabited α] [inhabited β] {f : α → β → γ} :
id                        └───────┘    └───────┘              
src                       └───────┘     └───────┘
typ                       └───────┘    └───────┘              
4992    ∀ bs : list β, pointwise f [] bs = bs.map (f $ default α)
id       └┘   └──┘   └───────┘  └┘ └┘  └┘└──┘     └─────┘ 
src           └──┘    └───────┘   └┘       └──┘      └─────┘
typ      └┘   └──┘   └───────┘  └┘ └┘  └┘└──┘     └─────┘ 
4993  | []      := rfl
id     └┘         └─┘
src    └┘         └─┘
typ    └┘         └─┘
4994  | (b::bs) :=
id       └┘
src      └┘
typ      └┘
4995    by simp only [nil_pointwise bs, pointwise,
id                   └───────────┘ └┘  └───────┘
src       └─────────┘               └┘└───────┘└─
typ       └─────────┘└───────────┘└┘└┘└───────┘└─
doc       └─────────┘               └┘         └─
txt       └─────────┘               └┘         └─
par       └─────────┘               └┘         └─
pid           └──┘└┘               └┘         └─
st       └────────────────────────────────────────
4996       eq_self_iff_true, and_self, map]
id        └──────────────┘  └──────┘  └─┘
src  ────┘└──────────────┘└┘└──────┘└┘└─┘└─
typ  ────┘└──────────────┘└┘└──────┘└┘└─┘└─
doc  ────┘                └┘        └┘   └─
txt  ────┘                └┘        └┘   └─
par  ────┘                └┘        └┘   └─
pid  ────┘                └┘        └┘   
st   ──────────────────────────────────────
4997  
src  
typ  
doc  
txt  
par  
pid  
st   
4998  lemma pointwise_nil [inhabited α] [inhabited β] {f : α → β → γ} :
id                        └───────┘    └───────┘              
src                       └───────┘     └───────┘
typ                       └───────┘    └───────┘              
4999    ∀ as : list α, pointwise f as [] = as.map (λ a, f a $ default β)
id       └┘   └──┘   └───────┘  └┘ └┘  └┘└──┘          └─────┘ 
src           └──┘    └───────┘      └┘    └──┘             └─────┘
typ      └┘   └──┘   └───────┘  └┘ └┘  └┘└──┘          └─────┘ 
5000  | []      := rfl
id     └┘         └─┘
src    └┘         └─┘
typ    └┘         └─┘
5001  | (a::as) :=
id       └┘
src      └┘
typ      └┘
5002    by simp only [pointwise_nil as, pointwise,
id                   └───────────┘ └┘  └───────┘
src       └─────────┘               └┘└───────┘└─
typ       └─────────┘└───────────┘└┘└┘└───────┘└─
doc       └─────────┘               └┘         └─
txt       └─────────┘               └┘         └─
par       └─────────┘               └┘         └─
pid           └──┘└┘               └┘         └─
st       └────────────────────────────────────────
5003       eq_self_iff_true, and_self, list.map]
id        └──────────────┘  └──────┘  └──────┘
src  ────┘└──────────────┘└┘└──────┘└┘└──────┘└─
typ  ────┘└──────────────┘└┘└──────┘└┘└──────┘└─
doc  ────┘                └┘        └┘        └─
txt  ────┘                └┘        └┘        └─
par  ────┘                └┘        └┘        └─
pid  ────┘                └┘        └┘        
st   ───────────────────────────────────────────
5004  
src  
typ  
doc  
txt  
par  
pid  
st   
5005  lemma get_pointwise [inhabited α] [inhabited β] [inhabited γ]
id                        └───────┘    └───────┘    └───────┘ 
src                       └───────┘     └───────┘     └───────┘
typ                       └───────┘    └───────┘    └───────┘ 
5006    {f : α → β → γ} (h1 : f (default α) (default β) = default γ) :
id                          └─────┘    └─────┘    └─────┘ 
src                             └─────┘     └─────┘     └─────┘
typ                         └─────┘    └─────┘    └─────┘ 
5007    ∀ (k : nat) (as : list α) (bs : list β),
id           └─┘        └──┘         └──┘ 
src           └─┘        └──┘          └──┘
typ          └─┘        └──┘         └──┘ 
5008    get k (pointwise f as bs) = f (get k as) (get k bs)
id     └─┘   └───────┘  └┘ └┘     └─┘  └┘   └─┘  └┘
src    └─┘    └───────┘              └─┘        └─┘
typ    └─┘   └───────┘  └┘ └┘     └─┘  └┘   └─┘  └┘
5009  | k [] [] := by simp only [h1, get_nil, pointwise, get]
id       └┘ └┘                  └┘  └─────┘  └───────┘  └─┘
src      └┘ └┘       └─────────┘  └┘└─────┘└┘└───────┘└┘└─┘└┘
typ      └┘ └┘       └─────────┘└┘└┘└─────┘└┘└───────┘└┘└─┘└┘
doc                  └─────────┘  └┘       └┘         └┘   └┘
txt                  └─────────┘  └┘       └┘         └┘   └┘
par                  └─────────┘  └┘       └┘         └┘   └┘
pid                      └──┘└┘  └┘       └┘         └┘   
st                  └───────────────────────────────────────┘
5010  | 0 [] (b::bs) :=
id       └┘   └┘
src      └┘   └┘
typ      └┘   └┘
5011    by simp only [get_pointwise, get_nil,
id                   └───────────┘  └─────┘
src       └─────────┘             └┘└─────┘└─
typ       └─────────┘└───────────┘└┘└─────┘└─
doc       └─────────┘             └┘       └─
txt       └─────────┘             └┘       └─
par       └─────────┘             └┘       └─
pid           └──┘└┘             └┘       └─
st       └───────────────────────────────────
5012        pointwise, get, nat.nat_zero_eq_zero, map]
id         └───────┘  └─┘  └──────────────────┘  └─┘
src  ─────┘└───────┘└┘└─┘└┘└──────────────────┘└┘└─┘└┘
typ  ─────┘└───────┘└┘└─┘└┘└──────────────────┘└┘└─┘└┘
doc  ─────┘         └┘   └┘                    └┘   └┘
txt  ─────┘         └┘   └┘                    └┘   └┘
par  ─────┘         └┘   └┘                    └┘   └┘
pid  ─────┘         └┘   └┘                    └┘   
st   ────────────────────────────────────────────────┘
5013  | (k+1) [] (b::bs) :=
id          └┘   └┘
src         └┘   └┘
typ         └┘   └┘
5014    by { have : get k (map (f $ default α) bs) = f (default α) (get k bs),
id                        └─┘                        └─────┘    └─┘  └┘
src         └─────┘     └─┘           └┘  └┘  └─────┘ └┘ └─┘   
typ         └─────┘     └─┘           └┘  └┘ └─────┘└┘ └─┘└┘
doc         └─────┘                   └┘  └┘           └┘       
txt         └─────┘                   └┘  └┘           └┘       
par         └─────┘                   └┘  └┘           └┘       
pid         └───┘└┘                   └┘  └┘           └┘       
st       └─────────────────────────────────────────────────────────────────┘└─
5015         { simpa [nil_pointwise, get_nil] using (get_pointwise k [] bs) },
id                   └───────────┘  └─────┘         └───────────┘  └┘ └┘
src           └─────┘└───────────┘└┘└─────┘└──────┘               └┘  └┘
typ           └─────┘└───────────┘└┘└─────┘└──────┘ └───────────┘└┘└┘└┘
doc           └─────┘             └┘       └──────┘                   └┘
txt           └─────┘             └┘       └──────┘                   └┘
par           └─────┘             └┘       └──────┘                   └┘
pid                             └┘       └────┘                   
st   ────────┘└───────────────────────────────────────────────────────────┘└┘
5016         simpa [get, get_nil, pointwise, map] }
id                 └─┘  └─────┘  └───────┘  └─┘
src         └─────┘└─┘└┘└─────┘└┘└───────┘└┘└─┘└┘
typ         └─────┘└─┘└┘└─────┘└┘└───────┘└┘└─┘└┘
doc         └─────┘   └┘       └┘         └┘   └┘
txt         └─────┘   └┘       └┘         └┘   └┘
par         └─────┘   └┘       └┘         └┘   └┘
pid                 └┘       └┘         └┘   
st   ───────────────────────────────────────────┘└┘
5017  | 0 (a::as) [] :=
id         └┘    └┘
src        └┘    └┘
typ        └┘    └┘
5018    by simp only [get_pointwise, get_nil,
id                   └───────────┘  └─────┘
src       └─────────┘             └┘└─────┘└─
typ       └─────────┘└───────────┘└┘└─────┘└─
doc       └─────────┘             └┘       └─
txt       └─────────┘             └┘       └─
par       └─────────┘             └┘       └─
pid           └──┘└┘             └┘       └─
st       └───────────────────────────────────
5019       pointwise, get, nat.nat_zero_eq_zero, map]
id        └───────┘  └─┘  └──────────────────┘  └─┘
src  ────┘└───────┘└┘└─┘└┘└──────────────────┘└┘└─┘└┘
typ  ────┘└───────┘└┘└─┘└┘└──────────────────┘└┘└─┘└┘
doc  ────┘         └┘   └┘                    └┘   └┘
txt  ────┘         └┘   └┘                    └┘   └┘
par  ────┘         └┘   └┘                    └┘   └┘
pid  ────┘         └┘   └┘                    └┘   
st   ───────────────────────────────────────────────┘
5020  | (k+1) (a::as) [] :=
id            └┘    └┘
src           └┘    └┘
typ           └┘    └┘
5021    by simpa [get, get_nil, pointwise, map, pointwise_nil, get_nil]
id               └─┘  └─────┘  └───────┘  └─┘  └───────────┘  └─────┘
src       └─────┘└─┘└┘└─────┘└┘└───────┘└┘└─┘└┘└───────────┘└┘└─────┘└─
typ       └─────┘└─┘└┘└─────┘└┘└───────┘└┘└─┘└┘└───────────┘└┘└─────┘└─
doc       └─────┘   └┘       └┘         └┘   └┘             └┘       └─
txt       └─────┘   └┘       └┘         └┘   └┘             └┘       └─
par       └─────┘   └┘       └┘         └┘   └┘             └┘       └─
pid               └┘       └┘         └┘   └┘             └┘       
st       └─────────────────────────────────────────────────────────────
5022       using get_pointwise k as []
id              └───────────┘  └┘ └┘
src  ──────────┘                └┘
typ  ──────────┘└───────────┘└┘└┘
doc  ──────────┘                  
txt  ──────────┘                  
par  ──────────┘                  
pid  ────┘└────┘                  
st   ────────────────────────────────┘
5023  | 0 (a::as) (b::bs) := by simp only [pointwise, get]
id         └┘      └┘                     └───────┘  └─┘
src        └┘      └┘          └─────────┘└───────┘└┘└─┘└┘
typ        └┘      └┘          └─────────┘└───────┘└┘└─┘└┘
doc                            └─────────┘         └┘   └┘
txt                            └─────────┘         └┘   └┘
par                            └─────────┘         └┘   └┘
pid                                └──┘└┘         └┘   
st                            └──────────────────────────┘
5024  | (k+1) (a::as) (b::bs) :=
id            └┘      └┘
src           └┘      └┘
typ           └┘      └┘
5025    by simp only [pointwise, get, get_pointwise k]
id                   └───────┘  └─┘  └───────────┘ 
src       └─────────┘└───────┘└┘└─┘└┘              └─
typ       └─────────┘└───────┘└┘└─┘└┘└───────────┘└─
doc       └─────────┘         └┘   └┘              └─
txt       └─────────┘         └┘   └┘              └─
par       └─────────┘         └┘   └┘              └─
pid           └──┘└┘         └┘   └┘              
st       └────────────────────────────────────────────
5026  
src  
typ  
doc  
txt  
par  
pid  
st   
5027  lemma length_pointwise [inhabited α] [inhabited β] {f : α → β → γ} :
id                           └───────┘    └───────┘              
src                          └───────┘     └───────┘
typ                          └───────┘    └───────┘              
5028    ∀ {as : list α} {bs : list β},
id            └──┘         └──┘ 
src            └──┘          └──┘
typ           └──┘         └──┘ 
5029    (pointwise f as bs).length = _root_.max as.length bs.length
id      └───────┘  └┘ └┘ └────┘   └────────┘ └┘└─────┘ └┘└─────┘
src     └───────┘         └────┘   └────────┘   └─────┘   └─────┘
typ     └───────┘  └┘ └┘ └────┘   └────────┘ └┘└─────┘ └┘└─────┘
5030  | []      []      := rfl
id     └┘      └┘         └─┘
src    └┘      └┘         └─┘
typ    └┘      └┘         └─┘
5031  | []      (b::bs) :=
id     └┘        └┘
src    └┘        └┘
typ    └┘        └┘
5032    by simp only [pointwise, length, length_map,
id                   └───────┘  └────┘  └────────┘
src       └─────────┘└───────┘└┘└────┘└┘└────────┘└─
typ       └─────────┘└───────┘└┘└────┘└┘└────────┘└─
doc       └─────────┘         └┘      └┘          └─
txt       └─────────┘         └┘      └┘          └─
par       └─────────┘         └┘      └┘          └─
pid           └──┘└┘         └┘      └┘          └─
st       └──────────────────────────────────────────
5033       max_eq_right (nat.zero_le (length bs + 1))]
id        └──────────┘  └─────────┘  └────┘ └┘ 
src  ────┘└──────────┘ └─────────┘ └────┘  └────┘
typ  ────┘└──────────┘ └─────────┘ └────┘└┘└────┘
doc  ────┘                                  └────┘
txt  ────┘                                  └────┘
par  ────┘                                  └────┘
pid  ────┘                                  └───┘
st   ────────────────────────────────────────────────┘
5034  | (a::as) []      :=
id       └┘    └┘
src      └┘    └┘
typ      └┘    └┘
5035    by simp only [pointwise, length, length_map,
id                   └───────┘  └────┘  └────────┘
src       └─────────┘└───────┘└┘└────┘└┘└────────┘└─
typ       └─────────┘└───────┘└┘└────┘└┘└────────┘└─
doc       └─────────┘         └┘      └┘          └─
txt       └─────────┘         └┘      └┘          └─
par       └─────────┘         └┘      └┘          └─
pid           └──┘└┘         └┘      └┘          └─
st       └──────────────────────────────────────────
5036       max_eq_left (nat.zero_le (length as + 1))]
id        └─────────┘  └─────────┘  └────┘ └┘
src  ────┘└─────────┘ └─────────┘ └────┘   └────┘
typ  ────┘└─────────┘ └─────────┘ └────┘└┘ └────┘
doc  ────┘                                 └────┘
txt  ────┘                                 └────┘
par  ────┘                                 └────┘
pid  ────┘                                 └───┘
st   ───────────────────────────────────────────────┘
5037  | (a::as) (b::bs) :=
id       └┘      └┘
src      └┘      └┘
typ      └┘      └┘
5038    by simp only [pointwise, length,
id                   └───────┘  └────┘
src       └─────────┘└───────┘└┘└────┘└─
typ       └─────────┘└───────┘└┘└────┘└─
doc       └─────────┘         └┘      └─
txt       └─────────┘         └┘      └─
par       └─────────┘         └┘      └─
pid           └──┘└┘         └┘      └─
st       └──────────────────────────────
5039       nat.max_succ_succ, @length_pointwise as bs]
id        └───────────────┘   └──────────────┘ └┘ └┘
src  ────┘└───────────────┘└┘                     └─
typ  ────┘└───────────────┘└┘ └──────────────┘└┘└┘└─
doc  ────┘                 └┘                     └─
txt  ────┘                 └┘                     └─
par  ────┘                 └┘                     └─
pid  ────┘                 └┘                     
st   ─────────────────────────────────────────────────
5040  
src  
typ  
doc  
txt  
par  
pid  
st   
5041  /- add -/
src  ──────────
typ  ──────────
doc  ──────────
txt  ──────────
par  ──────────
pid  ──────────
st   ──────────
5042  
src  
typ  
doc  
txt  
par  
pid  
st   
5043  @[simp] lemma get_add {α : Type u} [add_monoid α] {k : ℕ} {xs ys : list α} :
id                                       └────────┘                   └──┘ 
src                                      └────────┘                    └──┘
typ                                      └────────┘                   └──┘ 
doc    └──┘
5044    @get α ⟨0⟩ k (add xs ys) = ( @get α ⟨0⟩ k xs + @get α ⟨0⟩ k ys) :=
id      └─┘        └─┘ └┘ └┘      └─┘       └┘   └─┘       └┘
src     └─┘          └─┘            └─┘              └─┘
typ     └─┘        └─┘ └┘ └┘      └─┘       └┘   └─┘       └┘
5045  by {apply get_pointwise, apply zero_add}
id             └───────────┘        └──────┘
src      └────┘└───────────┘  └────┘└──────┘
typ      └────┘└───────────┘  └────┘└──────┘
doc      └────┘               └────┘
txt      └────┘               └────┘
par      └────┘               └────┘
pid                               
st     └───────────────────┘└──────────────┘└┘
5046  
5047  @[simp] lemma length_add {α : Type u}
doc    └──┘
5048    [has_zero α] [has_add α] {xs ys : list α} :
id      └──────┘    └─────┘            └──┘ 
src     └──────┘     └─────┘             └──┘
typ     └──────┘    └─────┘            └──┘ 
5049    (add xs ys).length = _root_.max xs.length ys.length :=
id      └─┘ └┘ └┘ └────┘   └────────┘ └┘└─────┘ └┘└─────┘
src     └─┘       └────┘   └────────┘   └─────┘   └─────┘
typ     └─┘ └┘ └┘ └────┘   └────────┘ └┘└─────┘ └┘└─────┘
5050  @length_pointwise α α α ⟨0⟩ ⟨0⟩ _ _ _
id    └──────────────┘   
src   └──────────────┘
typ   └──────────────┘   
5051  
5052  @[simp] lemma nil_add {α : Type u} [add_monoid α]
id                                       └────────┘ 
src                                      └────────┘
typ                                      └────────┘ 
doc    └──┘
5053    (as : list α) : add [] as = as :=
id           └──┘     └─┘ └┘ └┘  └┘
src          └──┘      └─┘ └┘    
typ          └──┘     └─┘ └┘ └┘  └┘
5054  begin
st   └─────
5055    rw [add, @nil_pointwise α α α ⟨0⟩ ⟨0⟩],
id         └─┘   └───────────┘     
src    └──┘└─┘└┘ └───────────┘    └─┘ └─┘
typ    └──┘└─┘└┘ └───────────┘   └─┘ └─┘
doc    └──┘   └┘                  └─┘ └─┘
txt    └──┘   └┘                  └─┘ └─┘
par    └──┘   └┘                  └─┘ └─┘
pid      └┘   └┘                  └─┘ └─┘
st   ────────┘└────────────────────────────┘└──
5056    apply eq.trans _ (map_id as),
id           └──────┘    └────┘ └┘
src    └────┘└──────┘└─┘ └────┘  
typ    └────┘└──────┘└─┘ └────┘└┘
doc    └────┘        └─┘         
txt    └────┘        └─┘         
par    └────┘        └─┘         
pid                 └─┘         
st   ─────────────────────────────┘└─
5057    congr, ext,
src    └───┘  └─┘
typ    └───┘  └─┘
doc           └─┘
txt    └───┘  └─┘
par    └───┘  └─┘
st   ──────┘└───┘└─
5058    have : @default α ⟨0⟩ = 0 := rfl,
id             └─────┘            └─┘
src    └─────┘ └─────┘  └─┘└────┘└─┘
typ    └─────┘ └─────┘ └─┘└────┘└─┘
doc    └─────┘          └─┘ └────┘
txt    └─────┘          └─┘ └────┘
par    └─────┘          └─┘ └────┘
pid    └───┘└┘          └─┘ └───┘
st   ─────────────────────────────────┘└─
5059    rw [this, zero_add], refl
id         └──┘  └──────┘
src    └──┘    └┘└──────┘  └───┘
typ    └──┘└──┘└┘└──────┘  └───┘
doc    └──┘    └┘          └───┘
txt    └──┘    └┘          └───┘
par    └──┘    └┘          └───┘
pid      └┘    └┘              
st   ─────────┘└────────┘└──────┘
5060  end
st   └─┘
5061  
5062  @[simp] lemma add_nil {α : Type u} [add_monoid α]
id                                       └────────┘ 
src                                      └────────┘
typ                                      └────────┘ 
doc    └──┘
5063    (as : list α) : add as [] = as :=
id           └──┘     └─┘ └┘ └┘  └┘
src          └──┘      └─┘    └┘ 
typ          └──┘     └─┘ └┘ └┘  └┘
5064  begin
st   └─────
5065    rw [add, @pointwise_nil α α α ⟨0⟩ ⟨0⟩],
id         └─┘   └───────────┘     
src    └──┘└─┘└┘ └───────────┘    └─┘ └─┘
typ    └──┘└─┘└┘ └───────────┘   └─┘ └─┘
doc    └──┘   └┘                  └─┘ └─┘
txt    └──┘   └┘                  └─┘ └─┘
par    └──┘   └┘                  └─┘ └─┘
pid      └┘   └┘                  └─┘ └─┘
st   ────────┘└────────────────────────────┘└──
5066    apply eq.trans _ (map_id as),
id           └──────┘    └────┘ └┘
src    └────┘└──────┘└─┘ └────┘  
typ    └────┘└──────┘└─┘ └────┘└┘
doc    └────┘        └─┘         
txt    └────┘        └─┘         
par    └────┘        └─┘         
pid                 └─┘         
st   ─────────────────────────────┘└─
5067    congr, ext,
src    └───┘  └─┘
typ    └───┘  └─┘
doc           └─┘
txt    └───┘  └─┘
par    └───┘  └─┘
st   ──────┘└───┘└─
5068    have : @default α ⟨0⟩ = 0 := rfl,
id             └─────┘            └─┘
src    └─────┘ └─────┘  └─┘└────┘└─┘
typ    └─────┘ └─────┘ └─┘└────┘└─┘
doc    └─────┘          └─┘ └────┘
txt    └─────┘          └─┘ └────┘
par    └─────┘          └─┘ └────┘
pid    └───┘└┘          └─┘ └───┘
st   ─────────────────────────────────┘└─
5069    rw [this, add_zero], refl
id         └──┘  └──────┘
src    └──┘    └┘└──────┘  └───┘
typ    └──┘└──┘└┘└──────┘  └───┘
doc    └──┘    └┘          └───┘
txt    └──┘    └┘          └───┘
par    └──┘    └┘          └───┘
pid      └┘    └┘              
st   ─────────┘└────────┘└──────┘
5070  end
st   └─┘
5071  
5072  lemma map_add_map {α : Type u} [add_monoid α] (f g : α → α) {as : list α} :
id                                   └────────┘                     └──┘ 
src                                  └────────┘                        └──┘
typ                                  └────────┘                     └──┘ 
5073    add (as.map f) (as.map g) = as.map (λ x, f x + g x) :=
id     └─┘  └┘└──┘    └┘└──┘    └┘└──┘          
src    └─┘    └──┘       └──┘       └──┘           
typ    └─┘  └┘└──┘    └┘└──┘    └┘└──┘          
5074  begin
st   └─────
5075    apply @eq_of_equiv _ (⟨0⟩ : inhabited α),
id            └─────────┘          └───────┘ 
src    └────┘ └─────────┘└─┘  └───┘└───────┘ 
typ    └────┘ └─────────┘└─┘  └───┘└───────┘
doc    └────┘            └─┘  └───┘          
txt    └────┘            └─┘  └───┘          
par    └────┘            └─┘  └───┘          
pid                     └─┘  └───┘          
st   ─────────────────────────────────────────┘└─
5076    { rw [length_map, length_add, max_eq_left, length_map],
id           └────────┘  └────────┘  └─────────┘  └────────┘
src      └──┘└────────┘└┘└────────┘└┘└─────────┘└┘└────────┘
typ      └──┘└────────┘└┘└────────┘└┘└─────────┘└┘└────────┘
doc      └──┘          └┘          └┘           └┘          
txt      └──┘          └┘          └┘           └┘          
par      └──┘          └┘          └┘           └┘          
pid        └┘          └┘          └┘           └┘          
st   ───┘└────────────┘└──────────┘└───────────┘└──────────┘└──
5077      apply le_of_eq,
id             └──────┘
src      └────┘└──────┘
typ      └────┘└──────┘
doc      └────┘
txt      └────┘
par      └────┘
pid           
st   ─────────────────┘└─
5078      rw [length_map, length_map] },
id           └────────┘  └────────┘
src      └──┘└────────┘└┘└────────┘└┘
typ      └──┘└────────┘└┘└────────┘└┘
doc      └──┘          └┘          └┘
txt      └──┘          └┘          └┘
par      └──┘          └┘          └┘
pid        └┘          └┘          
st   ─────────────────┘└──────────┘└┘
5079    intros m,
src    └──────┘
typ    └──────┘
doc    └──────┘
txt    └──────┘
par    └──────┘
pid          └┘
st   ─────────┘└─
5080    rw [get_add],
id         └─────┘
src    └──┘└─────┘
typ    └──┘└─────┘
doc    └──┘       
txt    └──┘       
par    └──┘       
pid      └┘       
st   ────────────┘└──
5081    by_cases h : m < length as,
id                    └────┘ └┘
src    └───────┘ └─┘ └────┘
typ    └───────┘ └─┘└────┘└┘
doc    └───────┘ └─┘        
txt    └───────┘ └─┘        
par    └───────┘ └─┘        
pid             └─┘        
st   ───────────────────────────┘└─
5082    { repeat {rw [@get_map α α ⟨0⟩ ⟨0⟩ _ _ _ h]} },
id                    └─────┘                  
src      └──────┘└──┘ └─────┘   └─┘ └───────┘ └┘
typ      └──────┘└──┘ └─────┘  └─┘ └───────┘└┘
doc      └──────┘└──┘           └─┘ └───────┘ └┘
txt      └──────┘└──┘           └─┘ └───────┘ └┘
par      └──────┘└──┘           └─┘ └───────┘ └┘
pid            └────┘           └─┘ └───────┘ └┘
st   ───┘└──────────────────────────────────────┘└┘└┘
5083    rw not_lt at h,
id        └────┘
src    └─┘└────┘└───┘
typ    └─┘└────┘└───┘
doc    └─┘      └───┘
txt    └─┘      └───┘
par    └─┘      └───┘
pid            └───┘
st   ───────────────┘└─
5084    repeat {rw [get_eq_default_of_le m]};
id                 └──────────────────┘ 
src    └──────┘└──┘└──────────────────┘ 
typ    └──────┘└──┘└──────────────────┘
doc    └──────┘└──┘                     
txt    └──────┘└──┘                     
par    └──────┘└──┘                     
pid          └────┘                     └┘
st   ───────────────────────────────────┘└─┘
5085    try {rw length_map, apply h},
id             └────────┘
src    └───┘└─┘└────────┘└┘└────┘ 
typ    └───┘└─┘└────────┘└┘└────┘ 
doc    └───┘└─┘          └┘└────┘ 
txt    └───┘└─┘          └┘└────┘ 
par    └───┘└─┘          └┘└────┘ 
pid       └───┘          └──────┘ 
st   ──────┘└───────────┘└───────┘└┘
5086    apply zero_add
id           └──────┘
src    └────┘└──────┘
typ    └────┘└──────┘
doc    └────┘        
txt    └────┘        
par    └────┘        
pid                 
st   ────────────────┘
5087  end
st   └─┘
5088  
5089  /- sub -/
5090  
5091  @[simp] lemma get_sub {α : Type u}
doc    └──┘
5092    [add_group α] {k : ℕ} {xs ys : list α} :
id      └───────┘                   └──┘ 
src     └───────┘                    └──┘
typ     └───────┘                   └──┘ 
5093    @get α ⟨0⟩ k (sub xs ys) = (@get α ⟨0⟩ k xs - @get α ⟨0⟩ k ys) :=
id      └─┘        └─┘ └┘ └┘     └─┘       └┘   └─┘       └┘
src     └─┘          └─┘           └─┘              └─┘
typ     └─┘        └─┘ └┘ └┘     └─┘       └┘   └─┘       └┘
5094  by {apply get_pointwise, apply sub_zero}
id             └───────────┘        └──────┘
src      └────┘└───────────┘  └────┘└──────┘
typ      └────┘└───────────┘  └────┘└──────┘
doc      └────┘               └────┘
txt      └────┘               └────┘
par      └────┘               └────┘
pid                               
st     └───────────────────┘└──────────────┘└┘
5095  
5096  @[simp] lemma length_sub [has_zero α] [has_sub α] {xs ys : list α} :
id                             └──────┘    └─────┘            └──┘ 
src                            └──────┘     └─────┘             └──┘
typ                            └──────┘    └─────┘            └──┘ 
doc    └──┘
5097    (sub xs ys).length = _root_.max xs.length ys.length :=
id      └─┘ └┘ └┘ └────┘   └────────┘ └┘└─────┘ └┘└─────┘
src     └─┘       └────┘   └────────┘   └─────┘   └─────┘
typ     └─┘ └┘ └┘ └────┘   └────────┘ └┘└─────┘ └┘└─────┘
5098  @length_pointwise α α α ⟨0⟩ ⟨0⟩ _ _ _
id    └──────────────┘   
src   └──────────────┘
typ   └──────────────┘   
5099  
5100  @[simp] lemma nil_sub {α : Type} [add_group α]
id                                     └───────┘ 
src                                    └───────┘
typ                                    └───────┘ 
doc    └──┘
5101    (as : list α) : sub [] as = neg as :=
id           └──┘     └─┘ └┘ └┘  └─┘ └┘
src          └──┘      └─┘ └┘     └─┘
typ          └──┘     └─┘ └┘ └┘  └─┘ └┘
5102  begin
st   └─────
5103    rw [sub, nil_pointwise],
id         └─┘  └───────────┘
src    └──┘└─┘└┘└───────────┘
typ    └──┘└─┘└┘└───────────┘
doc    └──┘   └┘             
txt    └──┘   └┘             
par    └──┘   └┘             
pid      └┘   └┘             
st   ────────┘└─────────────┘└──
5104    congr, ext,
src    └───┘  └─┘
typ    └───┘  └─┘
doc           └─┘
txt    └───┘  └─┘
par    └───┘  └─┘
st   ──────┘└───┘└─
5105    have : @default α ⟨0⟩ = 0 := rfl,
id             └─────┘            └─┘
src    └─────┘ └─────┘  └─┘└────┘└─┘
typ    └─────┘ └─────┘ └─┘└────┘└─┘
doc    └─────┘          └─┘ └────┘
txt    └─────┘          └─┘ └────┘
par    └─────┘          └─┘ └────┘
pid    └───┘└┘          └─┘ └───┘
st   ─────────────────────────────────┘└─
5106    rw [this, zero_sub]
id         └──┘  └──────┘
src    └──┘    └┘└──────┘└┘
typ    └──┘└──┘└┘└──────┘└┘
doc    └──┘    └┘        └┘
txt    └──┘    └┘        └┘
par    └──┘    └┘        └┘
pid      └┘    └┘        
st   ─────────┘└────────┘
5107  end
st   └─┘
5108  
5109  @[simp] lemma sub_nil {α : Type} [add_group α]
id                                     └───────┘ 
src                                    └───────┘
typ                                    └───────┘ 
doc    └──┘
5110    (as : list α) : sub as [] = as :=
id           └──┘     └─┘ └┘ └┘  └┘
src          └──┘      └─┘    └┘ 
typ          └──┘     └─┘ └┘ └┘  └┘
5111  begin
st   └─────
5112    rw [sub, pointwise_nil],
id         └─┘  └───────────┘
src    └──┘└─┘└┘└───────────┘
typ    └──┘└─┘└┘└───────────┘
doc    └──┘   └┘             
txt    └──┘   └┘             
par    └──┘   └┘             
pid      └┘   └┘             
st   ────────┘└─────────────┘└──
5113    apply eq.trans _ (map_id as),
id           └──────┘    └────┘ └┘
src    └────┘└──────┘└─┘ └────┘  
typ    └────┘└──────┘└─┘ └────┘└┘
doc    └────┘        └─┘         
txt    └────┘        └─┘         
par    └────┘        └─┘         
pid                 └─┘         
st   ─────────────────────────────┘└─
5114    congr, ext,
src    └───┘  └─┘
typ    └───┘  └─┘
doc           └─┘
txt    └───┘  └─┘
par    └───┘  └─┘
st   ──────┘└───┘└─
5115    have : @default α ⟨0⟩ = 0 := rfl,
id             └─────┘            └─┘
src    └─────┘ └─────┘  └─┘└────┘└─┘
typ    └─────┘ └─────┘ └─┘└────┘└─┘
doc    └─────┘          └─┘ └────┘
txt    └─────┘          └─┘ └────┘
par    └─────┘          └─┘ └────┘
pid    └───┘└┘          └─┘ └───┘
st   ─────────────────────────────────┘└─
5116    rw [this, sub_zero], refl
id         └──┘  └──────┘
src    └──┘    └┘└──────┘  └───┘
typ    └──┘└──┘└┘└──────┘  └───┘
doc    └──┘    └┘          └───┘
txt    └──┘    └┘          └───┘
par    └──┘    └┘          └───┘
pid      └┘    └┘              
st   ─────────┘└────────┘└──────┘
5117  end
st   └─┘
5118  
5119  end func
5120  
5121  namespace nat
5122  
5123  /-- The antidiagonal of a natural number `n` is the list of pairs `(i,j)` such that `i+j = n`. -/
5124  def antidiagonal (n : ℕ) : list (ℕ × ℕ) :=
id                             └──┘    
src                            └──┘    
typ                            └──┘    
5125  (range (n+1)).map (λ i, (i, n - i))
id    └───┘     └─┘           
src   └───┘      └─┘             
typ   └───┘     └─┘           
5126  
5127  /-- A pair (i,j) is contained in the antidiagonal of `n` if and only if `i+j=n`. -/
5128  @[simp] lemma mem_antidiagonal {n : ℕ} {x : ℕ × ℕ} :
id                                                
src                                               
typ                                               
doc    └──┘
5129    x ∈ antidiagonal n ↔ x.1 + x.2 = n :=
id       └──────────┘         
src       └──────────┘           
typ      └──────────┘         
doc        └──────────┘
5130  begin
st   └─────
5131    rw [antidiagonal, mem_map], split,
id         └──────────┘  └─────┘
src    └──┘└──────────┘└┘└─────┘  └───┘
typ    └──┘└──────────┘└┘└─────┘  └───┘
doc    └──┘└──────────┘└┘         └───┘
txt    └──┘            └┘         └───┘
par    └──┘            └┘         └───┘
pid      └┘            └┘       
st   ─────────────────┘└───────┘└──────┘└─
5132    { rintros ⟨i, hi, rfl⟩, rw [mem_range, lt_succ_iff] at hi, exact add_sub_of_le hi },
id                                 └───────┘  └─────────┘               └───────────┘ └┘
src      └──────────────────┘  └──┘└───────┘└┘└─────────┘└─────┘  └────┘└───────────┘  
typ      └──────────────────┘  └──┘└───────┘└┘└─────────┘└─────┘  └────┘└───────────┘└┘
doc      └──────────────────┘  └──┘         └┘           └─────┘  └────┘               
txt      └──────────────────┘  └──┘         └┘           └─────┘  └────┘               
par      └──────────────────┘  └──┘         └┘           └─────┘  └────┘               
pid             └───────────┘    └┘         └┘           └────┘                      
st   ───┘└──────────────────┘└─────────────┘└───────────┘└────┘└───────────────────────┘└┘
5133    { rintro rfl, refine ⟨x.fst, _, _⟩,
id                           └───┘
src      └────────┘  └─────┘ └───┘└─────┘
typ      └────────┘  └─────┘ └───┘└─────┘
doc      └────────┘  └─────┘      └─────┘
txt      └────────┘  └─────┘      └─────┘
par      └────────┘  └─────┘      └─────┘
pid            └──┘              └─────┘
st   ─────────────┘└────────────────────┘└─
5134      { rw [mem_range, add_assoc, lt_add_iff_pos_right], exact zero_lt_succ _ },
id             └───────┘  └───────┘  └──────────────────┘         └──────────┘
src        └──┘└───────┘└┘└───────┘└┘└──────────────────┘  └────┘└──────────┘└─┘
typ        └──┘└───────┘└┘└───────┘└┘└──────────────────┘  └────┘└──────────┘└─┘
doc        └──┘         └┘         └┘                      └────┘            └─┘
txt        └──┘         └┘         └┘                      └────┘            └─┘
par        └──┘         └┘         └┘                      └────┘            └─┘
pid          └┘         └┘         └┘                                       └┘
st   ─────┘└───────────┘└─────────┘└────────────────────┘└──────────────────────┘└┘
5135      { exact prod.ext rfl (nat.add_sub_cancel_left _ _) } }
id               └──────┘ └─┘  └─────────────────────┘
src        └────┘└──────┘└─┘ └─────────────────────┘└────┘
typ        └────┘└──────┘└─┘ └─────────────────────┘└────┘
doc        └────┘                                   └────┘
txt        └────┘                                   └────┘
par        └────┘                                   └────┘
pid                                                └───┘
st   ──────────────────────────────────────────────────────┘└───
5136  end
st   ──┘
5137  
5138  /-- The length of the antidiagonal of `n` is `n+1`. -/
5139  @[simp] lemma length_antidiagonal (n : ℕ) : (antidiagonal n).length = n+1 :=
id                                               └──────────┘  └────┘   
src                                              └──────────┘   └────┘    
typ                                              └──────────┘  └────┘   
doc    └──┘                                       └──────────┘
5140  by rw [antidiagonal, length_map, length_range]
id          └──────────┘  └────────┘  └──────────┘
src     └──┘└──────────┘└┘└────────┘└┘└──────────┘└─
typ     └──┘└──────────┘└┘└────────┘└┘└──────────┘└─
doc     └──┘└──────────┘└┘          └┘            └─
txt     └──┘            └┘          └┘            └─
par     └──┘            └┘          └┘            └─
pid       └┘            └┘          └┘            
st     └───────────────┘└──────────┘└────────────┘
5141  
src  
typ  
doc  
txt  
par  
pid  
st   
5142  /-- The antidiagonal of `0` is the list `[(0,0)]` -/
5143  @[simp] lemma antidiagonal_zero : antidiagonal 0 = [(0, 0)] :=
id                                     └──────────┘         
src                                    └──────────┘         
typ                                    └──────────┘         
doc    └──┘                            └──────────┘
5144  ext_le (length_antidiagonal 0) $ λ n h₁ h₂,
id   └────┘  └─────────────────┘         └┘ └┘
src  └────┘  └─────────────────┘
typ  └────┘  └─────────────────┘         └┘ └┘
doc          └─────────────────┘
5145  begin
st   └─────
5146    rw [length_antidiagonal, lt_succ_iff, le_zero_iff] at h₁,
id         └─────────────────┘  └─────────┘  └─────────┘
src    └──┘└─────────────────┘└┘└─────────┘└┘└─────────┘└─────┘
typ    └──┘└─────────────────┘└┘└─────────┘└┘└─────────┘└─────┘
doc    └──┘└─────────────────┘└┘           └┘           └─────┘
txt    └──┘                   └┘           └┘           └─────┘
par    └──┘                   └┘           └┘           └─────┘
pid      └┘                   └┘           └┘           └────┘
st   ────────────────────────┘└───────────┘└───────────┘└────┘└─
5147    subst n, simp [antidiagonal]
id                   └──────────┘
src    └────┘   └────┘└──────────┘└┘
typ    └────┘  └────┘└──────────┘└┘
doc    └────┘   └────┘└──────────┘└┘
txt    └────┘   └────┘            └┘
par    └────┘   └────┘            └┘
pid                            
st   ────────┘└────────────────────┘
5148  end
st   └─┘
5149  
5150  /-- The antidiagonal of `n` does not contain duplicate entries. -/
5151  lemma nodup_antidiagonal (n : ℕ) : nodup (antidiagonal n) :=
id                                     └───┘  └──────────┘ 
src                                    └───┘  └──────────┘
typ                                    └───┘  └──────────┘ 
doc                                     └───┘  └──────────┘
5152  nodup_map (@injective_of_left_inverse ℕ (ℕ × ℕ) prod.fst (λ i, (i, n-i)) $ λ i, rfl) (nodup_range _)
id   └───────┘   └───────────────────────┘       └──────┘                 └─┘   └─────────┘
src  └───────┘   └───────────────────────┘       └──────┘                      └─┘   └─────────┘
typ  └───────┘   └───────────────────────┘       └──────┘                 └─┘   └─────────┘
5153  
5154  end nat
5155  
5156  end list
5157  
5158  theorem option.to_list_nodup {α} : ∀ o : option α, o.to_list.nodup
id                                           └────┘   └──────┘└────┘
src                                           └────┘     └──────┘└────┘
typ                                          └────┘   └──────┘└────┘
doc                                                              └────┘
5159  | none     := list.nodup_nil
id     └──┘        └────────────┘
src    └──┘        └────────────┘
typ    └──┘        └────────────┘
5160  | (some x) := list.nodup_singleton x
id      └──┘      └──────────────────┘
src     └──┘       └──────────────────┘
typ     └──┘      └──────────────────┘
5161  
5162  @[to_additive]
doc    └─────────┘
5163  theorem monoid_hom.map_list_prod {α β : Type*} [monoid α] [monoid β] (f : α →* β) (l : list α) :
id                                                   └────┘    └────┘         └┘        └──┘ 
src                                                  └────┘     └────┘           └┘         └──┘
typ                                                  └────┘    └────┘         └┘        └──┘ 
doc                                                                              └┘
5164    f l.prod = (l.map f).prod :=
id      └───┘   └──┘  └──┘
src       └───┘    └──┘   └──┘
typ     └───┘   └──┘  └──┘
doc       └───┘            └──┘
5165  (l.prod_hom f).symm
id    └───────┘  └──┘
src    └───────┘   └──┘
typ   └───────┘  └──┘